Reputation: 464
I have the following code:
foo_list = Foo.objects.all()[100:200]
print foo_list[0].id
print len(foo_list)
print foo_list[0].id
I expect that result of first and third print be eqaul but they are not.How this could be happen?
Upvotes: 2
Views: 116
Reputation: 59425
The reason is that querysets are lazy.
When you construct your foo_list
in the first line, nothing happens on database. The query is not executed until you actually get an object from the queryset.
So, when you get foo_list[0].id
for the first time, you actually re-slice it, thus running a SELECT
statement asking for a single row. Now, when you call len(foo_list)
you force the original queryset (which returns 100 rows) to be executed.
Since you run two different queries (one for a single row, and one for 100 rows) and did not specify an order_by
clause, the two queries may (and do) return different results.
Upvotes: 0
Reputation: 882501
You're running into the "wontfix" issue at https://code.djangoproject.com/ticket/9006 --
LIMIT queries without ORDER BY aren't guaranteed to return consistent result sets
(depending on the underlying DB engine), and that's what your [0]
indexing is causing to happen -- because despite the misleading name foo_list
is not a list, it's queryset itself! As documented at https://docs.djangoproject.com/en/1.7/ref/models/querysets/ ,
Slicing an unevaluated
QuerySet
usually returns another unevaluatedQuerySet
Solution: make it a list:
foo_list = list(Foo.objects.all()[100:200])
and live happily ever after:-)
Upvotes: 4