当强制转换为列表时,Django查询集结果的长度会发生变化

时间:2017-10-31 14:08:52

标签: python django django-queryset

因此我有一个相当复杂的查询集,它通过isoweek汇总数据:

>>> MyThing.objects.all().count()
30000

>>> qs = MyThing.objects.all().order_by('date').annotate(
    dw=DateWeek('date'), # uses WEEK function
    dy=ExtractYear('date')
).values(
    'dy','dw','group_id'
).annotate(
    sum_count=Sum('count')
).values_list('dw', 'dy', 'group_id', 'sum_count')

>>> qs.count()
2000

到目前为止一切顺利。问题是当我将此查询集强制转换为列表时:

>>> len(list(qs))
30000

为什么会这样?如何直接count()获取查询集声称具有的分组值列表?

1 个答案:

答案 0 :(得分:1)

要解决此问题,请删除.order_by('date')。虽然它没有包含在输出中,但数据库后端仍然在每行考虑它,导致行数膨胀。

如果要在添加这些注释后对输出.order_by('dy', 'dw')进行排序。

您还可以添加一个不带参数的.order_by()来清除以前的任何排序集,例如从Model类定义默认排序。

django docs

中解释了此行为的原因
  

order_by()来电中使用的所有字段都包含在SQL SELECT中   列。这在使用时有时会导致意想不到的结果   与distinct()合作。如果您按相关字段排序   模型,这些字段将添加到选定的列,他们可能会   否则重复的行似乎是不同的。额外的   列不会出现在返回的结果中(它们只出现在那里)   支持订购),它有时看起来像非截然不同的结果   被退回。

     

同样,如果您使用values()查询来限制列   选中,任何order_by()(或默认模型)中使用的列   订购)仍将涉及并可能影响的独特性   结果

     

这里的道德是,如果你使用distinct()要小心   按相关型号订购。同样,使用distinct()和时   values()在一起,按照不在的字段排序时要小心   values()致电。