julx
julx

Reputation: 9091

QuerySet caching: executing get after filter was fired

How many database queries will be executed for the following code:

q = SomeModel.objects.filter(pk__in=ids)
print q    # The actual query is executed and the result 
           # set evaluated
m = q.get(pk=ids[0])
print m    # Does it reuse the evaluated result set 
           # or does it hit the database the second time?

Upvotes: 0

Views: 378

Answers (1)

Zach Kelling
Zach Kelling

Reputation: 53879

Since querysets are evaluated lazily if you do:

q = SomeModel.objects.filter(pk__in=ids)

...immediately folllowed by (i.e., without using print):

m = q.get(pk=ids[0])

You'll end up with one SQL query. It'll AND together the first query with the second. It's safe to continue adding to querysets this way. In Django 1.3 the logging is revamped and you can get nice logging in the interactive console:

>>> import logging
>>> l = logging.getLogger('django.db.backends')
>>> l.setLevel(logging.DEBUG)
>>> l.addHandler(logging.StreamHandler())

Which will give you this sort of debugging info as soon as an actual query is executed:

(0.013) SELECT "someapp_somemodel"."id", "someapp_somemodel"."question", "someapp_somemodel"."pub_date" FROM "someapp_somemodel" WHERE ("someapp_somemodel"."id" IN (0, 1) AND "someapp_somemodel"."id" = 0 ); args=(0, 1, 0)

Don't use get on a filtered queryset. If the model you want is in your queryset, use a Python expression (like a list comprehension or filter or such) to get the model instance out of your queryset, and avoid hitting the database at all a second time (or many more times if you iterate over a list of id's).

Upvotes: 1

Related Questions