Simeon Franklin

Blog :: Hidden Django QuerySet Features I

14 February 2011

I've been paying attention to the generated SQL the Django ORM provides lately. I've had to a bit of performance tuning on some apps I wrote so I started out with the django-debug-toolbar app which will show you all the queries run on a given page and their runtime. This is an indispensable tool in my daily toolkit but I wanted to play with creating queries in my console. How do I see the SQL that is generated?

Somewhere (probably just through introspection) I found the semi-private _as_sql() method.


>>> User.objects.filter(is_staff=True)._as_sql()
('SELECT U0."id" FROM "auth_user" U0 WHERE U0."is_staff" = %s ', (True,))

Notice that this doesn't return all the fields ("select id from..."). This method also won't work on value QuerySets and shouldn't be depended on as it is not a part of the public interface of the QuerySet class. It does helpfully returns a two part tuple of the query string with placeholders and a tuple containing the query parameters. This is useful if you want to tweak the parameters on the fly and paste them into a db console. A better method to get the sql actually being executed is to access the .query member of a QuerySet:


>>> users = User.objects.filter(is_staff=True)
>>> users.query
<django.db.models.sql.query.BaseQuery object at 0x9df63ac>
>>> str(users.query)
'SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", 
"auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", 
"auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", 
"auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."is_staff" = True '

Finally you can see all the queries that have run by looking at the connection object.


>>> from django.db import connection
>>> print connection.queries
[{'sql': 'SELECT ....',
  'time': '0.009'},]

I redacted the actual query but this returns rows of dicts with the sql that was run and how long it took to run.


blog comments powered by Disqus