django queryset中的意外行为

时间:2015-03-31 15:30:20

标签: python django django-queryset

我有以下代码:

foo_list = Foo.objects.all()[100:200]
print foo_list[0].id
print len(foo_list)
print foo_list[0].id

我希望第一次和第三次印刷的结果是eqaul,但它们不是。这怎么可能发生?

2 个答案:

答案 0 :(得分:4)

您在https://code.djangoproject.com/ticket/9006 -

遇到了“wontfix”问题
  

没有ORDER BY的LIMIT查询不保证返回一致   结果集

(取决于底层的数据库引擎),这就是您的[0]索引导致发生的事情 - 因为尽管误导性名称foo_list 不是列表,它的查询集本身!正如https://docs.djangoproject.com/en/1.7/ref/models/querysets/所述,

  

切片未评估的QuerySet通常会返回另一个未评估的值   QuerySet

解决方案:制作一个列表:

foo_list = list(Foo.objects.all()[100:200])

从此过上幸福的生活: - )

答案 1 :(得分:0)

原因是querysets are lazy

在第一行构建foo_list时,数据库上没有任何反应。在您实际从查询集中获取对象之前,不会执行查询。

因此,当您第一次获得foo_list[0].id时,实际上重新对其进行切片,从而运行SELECT语句,要求输入单行。现在,当您致电len(foo_list)时,强制原始查询集(返回100行)将被执行。

由于您运行两个不同的查询(一个用于单行,一个用于100行)并且未指定order_by子句,因此这两个查询可能(并且确实)返回不同的结果。