我有一个Word
模型
它有很多领域
Phrase
模型
我以json
格式将字词传递给前端,如下所示:
words_json = []
words = Word.objects.filter(....filter_by_some_params)
for word in words:
single_word_json = {}
single_word_json['id'] = word.id
single_word_json['name'] = word.name
single_word_json['count'] = len(word.phrases.all())
words_json.appen(word_json)
return words_json
我觉得这样是无效的,并且无法扩展(我将有1万个单词和短语,所以我该怎么办?
答案 0 :(得分:1)
您可以使用以下方法:
from django.db.models import Count
qs = Word.objects.filter(..).annotate(
count=Count('phrase')
).values('id', 'name', 'count')
那么您的words_json
就是:
words_json = list(qs)
.values()
将构建字典查询集。每个词典将包含三个项目:id
,name
和count
。 count
源自.annotate(..)
函数,我们在其中计算phrase
的数量。
这样做的好处是我们将在单个查询中完成所有处理,例如:
SELECT w.id, w.name, COUNT(wp.phrase_id)
FROM word AS w
LEFT OUTER JOIN word_phrase AS wp ON w.id = wp.word_id
GROUP BY w.id, w.name
因此,我们而不是 n + 1 个查询(其中 n 个是从Word
中出来的.filter(..)
个),因此,我们执行一个查询。此外,我们限制了数据库返回结果所需的带宽,并让Django为我们将响应包装成字典。
编辑:如果Word
到ForeignKey
的范围是Group
,并且您还希望包含该名称,则可以将其写为:
from django.db.models import Count, F
qs = Word.objects.filter(..).annotate(
count=Count('phrase'),
group_name=F('group__name')
).values('id', 'name', 'count', 'group_name')
现在,每个字典都将有一个额外的键group_name
。如果Word
没有Group
,则group_name
将是None
(或JSON中的null
)。