KongDeqiang
KongDeqiang

Reputation: 183

django Queryset became List after a for loop

I'm using django for my website ,the problem is hard to tell,please see code below.(python 2.7.10)

In [1]: user = User.objects.filter(pk__gt = 1)
In [2]: type(user)
Out[2]: django.db.models.query.QuerySet

In [3]: user1=user[0:user.count()]
In [4]: type(user1)
Out[4]: django.db.models.query.QuerySet

obviously ,user and user1 is QuerySet, now the problem come:

In [1]: user = User.objects.filter(pk__gt = 1)
In [2]: type(user)
Out[2]: django.db.models.query.QuerySet

In [3]: for i in user:pass
In [4]: user1=user[0:user.count()]
In [5]: type(user1)
Out[5]: list

The user is also QuerySet,but the user1 became list.

The only diffirent betweet these two code is a for loop

 for i in user:pass

I am confused about what happend in that for loop ?

Upvotes: 3

Views: 2099

Answers (1)

sthzg
sthzg

Reputation: 5554

By running the for loop you do what Django calls evaluating the QuerySet. Before that, it is said to be lazy, which means that adding filters and other QuerySet methods do not actually hit the database.

An interesting snippet from QuerySets are lazy (also see the example there):

QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated.

There are a few statements and methods that evaluate your QuerySet, which are documented in When QuerySets are evaluated and include iteration and slicing an already evaluated QuerySet.

What this means is that once you evaluate a queryset, e.g. through iteration which you did with the for loop, Django will actually query the database. Once that is done this paragraph from the docs sums up the behavior you get after slicing the QuerySet with user1=user[0:user.count()] on In [4] in your second shell snippet.

Slicing. As explained in Limiting QuerySets, a QuerySet can be sliced, using Python’s array-slicing syntax. Slicing an unevaluated QuerySet usually returns another unevaluated QuerySet, but Django will execute the database query if you use the “step” parameter of slice syntax, and will return a list. Slicing a QuerySet that has been evaluated also returns a list.

Upvotes: 4

Related Questions