16
Sep 09
Inspired by Cal Henderson's Keynote Presentation at
Django Con 2008 I have set out to implement better debugging for Django's SQL queries.
The goal is to tack on some helpful stack information as a comment at the end of every query. Once applied, when you have DEBUG set to True, queries show up like this example:
SELECT "django_content_type"."id", "django_content_type"."name", ... FROM "django_content_type" WHERE ("django_content_type"."model" = 'album' AND ... -- File ".../project/app/views.py", line 74, in fetch_contenttypes
Notice the last line which contains the comment. The snippet rolls back out of the Django internals to the last made call. At this point, which hopefully is someplace in your application, it appends the file, line number, and location to your query as an SQL comment. Here is the meat of the Python code:
if settings.DEBUG: import django from traceback import extract_stack from os.path import dirname stack = extract_stack() stack.reverse() dj_base = dirname(django.__file__) for frame in stack: if not frame[0].startswith(dj_base): sql += ' -- File "%s", line %d, in %s' % frame[:3] break
And here is the official patch im releasing against the trunk (but it should work on just about any recent release)
Index: django/db/models/sql/query.py =================================================================== --- django/db/models/sql/query.py (revision 11580) +++ django/db/models/sql/query.py (working copy) @@ -8,7 +8,7 @@ """ from copy import deepcopy - +from django.conf import settings from django.utils.tree import Node from django.utils.datastructures import SortedDict from django.utils.encoding import force_unicode @@ -2365,6 +2365,19 @@ return empty_iter() else: return + + if settings.DEBUG: + import django + from traceback import extract_stack + from os.path import dirname + stack = extract_stack() + stack.reverse() + dj_base = dirname(django.__file__) + for frame in stack: + if not frame[0].startswith(dj_base): + sql += ' -- File "%s", line %d, in %s' % frame[:3] + break + cursor = self.connection.cursor() cursor.execute(sql, params)
This is not to be used in a production setting, which is why it only comments your queries when DEBUG is True, but it is a very handy tool to nail down exactly where your queries are coming from in your application. I will probably eventually file a ticket to this effect and see how it is received (dont hold ur breath, im super lazy ;-P )