我有三个模型 Learner,Level和直通模型LearnerLevel。
模型如下所示:
class Learner(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
words = models.ManyToManyField('Word', through='LearnerWord', related_name='Learners')
levels = models.ManyToManyField('Level', through='LearnerLevel', related_name='Learners')
def __str__(self):
return self.user.username
class Level(models.Model):
name = models.CharField(max_length=100)
selectedByUser = models.BooleanField(default=False)
words = models.ManyToManyField('Word', through='LevelWord', related_name='levels')
countWords = models.IntegerField(default=0)
language = models.ForeignKey('Language', related_name='languagelevels', on_delete=models.CASCADE, null=True,
blank=True)
def __str__(self):
return self.name
class LearnerLevel(models.Model):
learner = models.ForeignKey('Learner', related_name='learnerlevels', on_delete=models.SET_NULL, null=True)
level = models.ForeignKey('Level', related_name='learnerlevels', on_delete=models.SET_NULL, null=True, blank=True)
knownWords = models.IntegerField(default=0)
def __str__(self):
return self.learner.user.username + ' ' + self.level.name
表格如下所示:
SELECT * FROM app_level;
id|name |countWords|language_id|selectedByUser
1 |A1 |0 |1 |0
2 |A1 Supermarkt |0 |1 |0
3 |A1 |22 |2 |0
4 |A1 Albanisch1 |20 |4 |0
5 |A1 Albanisch2 |17 |4 |0
6 |A1 Albanisch3 |21 |4 |0
7 |A1 Albanisch4 |20 |4 |0
8 |A1 Albanisch4 |20 |4 |0
9 |A1 Albanisch5 |20 | |0
10|A1 Albanisch7 |20 |4 |0
11|A1 Albanisch8 |20 |4 |0
12|A1 Albanisch9 |20 |4 |0
13|A1 Albanisch10|20 |4 |0
14|A1 Albanisch11|20 |4 |0
15|A1 Albanisch12|20 |4 |0
SELECT * FROM wordapp_learnerlevel;
id|knownWords|learner_id|level_id
1 |8 |1 |4
2 |16 |1 |5
3 |3 |1 |6
4 |8 |1 |1
5 |8 |2 |4
我的第一个问题是,如何使用 Django 实现以下目标?
SELECT wordapp_level.name,
wordapp_level.countWords,
wordapp_learnerlevel.knownWords
FROM wordapp_level
INNER JOIN wordapp_learnerlevel
ON wordapp_level.id = wordapp_learnerlevel.level_id;
name |countWords|knownWords
A1 Albanisch1|20 |8
A1 Albanisch2|17 |16
A1 Albanisch3|21 |3
A1 |0 |8
A1 Albanisch1|20 |8
我的目标是获得一个新的查询集,我可以从 django-rest-framework 的 get_queryset 函数中将其提供给模型视图。我的第二个问题是,这是好的做法吗?
我想要这样的东西:
def get_queryset(self):
learnerStatistic = LearnerLevel.objects.select_related('level')
return learnerStatistic
例如,学习者从 id 为 1 2 3 的级别学习。现在在 learnerlevel 中,knownWords 更改了 level_id 为 1 2 3 的位置。现在我想给用户一个统计信息。"你从level.name中学到了level.countWords的learnerlevel.knownWords "
从 Django 文档中我不清楚
========== 编辑 ==========
我试过了
str(LearnerLevel.objects.select_related('level').query)
我明白了
SELECT "wordapp_learnerlevel"."id", "wordapp_learnerlevel"."learner_id", "wordapp_learnerlevel"."level_id", "wordapp_learnerlevel"."knownWords", "wordapp_level"."id", "wordapp_level"."name", "wordapp_level"."selectedByUser", "wordapp_level"."countWords", "wordapp_level"."language_id" FROM "wordapp_learnerlevel" LEFT OUTER JOIN "wordapp_level" ON ("wordapp_learnerlevel"."level_id" = "wordapp_level"."id")'
但当
str(LearnerLevel.objects.select_related('level').values().query)
我明白了
SELECT "wordapp_learnerlevel"."id", "wordapp_learnerlevel"."learner_id", "wordapp_learnerlevel"."level_id", "wordapp_learnerlevel"."knownWords" FROM "wordapp_learnerlevel"
但我只想要learnerlevel.knownWords,level.countWords,level.name
如果我做
qs = LearnerLevel.objects.select_related('level').only('knownWords','level__name','level__countWords')
然后
qs.values()
是
<QuerySet [{'id': 1, 'learner_id': 1, 'level_id': 4, 'knownWords': 8}, {'id': 2, 'learner_id': 1, 'level_id': 5, 'knownWords': 16}, {'id': 3, 'learner_id': 1, 'level_id': 6, 'knownWords': 3}, {'id': 4, 'learner_id': 1, 'level_id': 1, 'knownWords': 8}, {'id': 5, 'learner_id': 2, 'level_id': 4, 'knownWords': 8}]>
但我希望它是
<QuerySet [{'id': 1, 'name': 'A1', 'knownWords': 8, 'countWords': xx}, .....]>
======解决方案======
我找到了解决方案
def get_queryset(self):
currLearner = Learner.objects.get(user=self.request.user)
return currLearner.learnerlevels.values('knownWords', 'level__name', 'level__countWords')
并且序列化器是
class LearnerLevelXXSerializer(serializers.Serializer):
knownWords = serializers.IntegerField()
level__name = serializers.CharField(max_length=200)
level__countWords = serializers.IntegerField()
谢谢丹尼斯·科内尔。你的建议帮助了我