Django 多对多计数和优化查询

Django 多对多计数和优化查询,django,python-3.x,Django,Python 3.x,我有一个Word模型 它有一个多对多字段 短语型号 我用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.

我有一个
Word
模型 它有一个多对多字段
短语
型号

我用
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

我觉得这样做没有效果,也无法扩展(我会有多达10000个单词和短语,那么我该怎么办?

您可以使用以下方法:

from django.db.models import Count

qs = Word.objects.filter(..).annotate(
    count=Count('phrase')
).values('id', 'name', 'count')
那么你的
words\u json
就是:

words_json = list(qs)
.values()
将构建一个字典查询集。每个字典将包含三项:
id
name
count
count
源于
.annotate(…)
函数,我们在其中计算
短语的数量

这样做的好处是,我们将在一个查询中完成所有处理,如:

选择w.id、w.name、COUNT(wp.phrase\u id)
从单词w开始
在w.id=wp.word\u id上作为wp的左外连接词\u短语
按w.id、w.name分组
因此,我们不执行n+1查询(n是
.filter(..)
中的
单词数),而是执行单个查询。此外,我们限制数据库返回结果所需的带宽,并让Django为我们将响应包装到字典中

编辑:如果一个
单词
有一个
外键
指向一个
,并且您还想包含名称,您可以这样写:

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')
从django.db.models导入计数,F
qs=Word.objects.filter(..).annotate(
count=count('短语'),
组名称=F('组名称')
).values('id','name','count','group\u name')

现在,每个字典都会有一个额外的键
组名
。如果
单词
没有
组名
,那么
组名
将是
(或者在JSON中为
).

还有一个问题:如果每个单词都有一个到
组的
外键
模型,我如何才能传递到我的结果列表
'Group.name
?那么你想在JSON blob中包含组名?然后你可以执行额外的注释,例如
组名=F('Group\u name'))
并将其包含在
值中。好的,还有最后一个问题:如果我需要向生成的对象传递一个空数组-如何使用annotate:
single_word_json['connected_words_to_check']=[]
@user2950593:不,那么您必须手动修补每个字典。但是这通常会很快,因为不涉及任何查询。如果可能的话,在查询集中注释常量实际上会比较慢。如果出现错误怎么办:注释
与字段组冲突。我可以做些什么吗是否在不重命名结果字段的情况下使用此选项?