Django: Debug techniques and IPython
Since joining The Lab, I have had the pleasure of working with Django a whole lot more. In this time, I’ve noticed a couple of tricks / niceties that make development run a lot smoother, here are a couple…
Evolution of debugging
Web development is full of little debug tricks, usually involving variations on variable inspection. Django provides lots of such useful methods, and I have found myself progressing through more powerful solutions as I discover them.
-
return HttpResponse({variable to inspect})
As far as I am aware, this is the most basic form of debugging. Just stick that string at the point in your view where you wish to examine the state and it will short circuit the view code with the variable result. It’s the Django equivalent of alert(). In a lot of development, this will suffice, however this is limited to the scope of view code.
-
print {variable to inspect}
Usable in any Django Python code running on the Django development server, lob this in and it will publish the result to the console. I usually put some \n’s around it to easier spot it amongst the response codes. For me, the limitation of only being able to use it in the dev server isn’t a big one, because that’s where I do most of my development. The only real issue is when I realise that I want a different variable, change the code and restart the server. Some debug context (solved by the next method) would be nice.
(#5677 suggests that this is bad form and could cause troubles when using over mod_python, depending on your set-up.)
-
raise Exception({variable to inspect})
I realised this beaut through the most excellent Django wiki. By raising the exception (with debug = True in your settings.py), you force the lovely Django debug page to display - chocked full with helpful info, tracebacks and context - along with your inspected variable at the top.
-
import pdb; pdb.set_trace()
This is my personal favourite. It activates the Python Debugger and allows you to step through your code and interactively check each variable.
Type “help” for a list of commands, “args” prints the arguments sent into the currently running function, “next” executes the next line, p {variable to inspect} prints a variable, pp {variable} pretty-prints a variable and continue tells pdb to run the rest of your code (unless we hit another breakpoint).
My google-fu has recently revealed django-logging, a Django middleware component which provides the ability to spit out variables in your view and based upon the Python Logging module. I am yet to try this, but it looks like another ace string in your Django debugging bow.
In addition to these, there is always the incredibly helpful <% debug %> tag, to spit out your context variables while template coding.
IPython
IPython has spoiled me rotten. It is an enhanced Python REPL environment with a lot of extra bells and whistles. First off, the code completion is fab. django-admin.py recognises that you have IPython installed, so typing “./manage.py shell” allows you to import your models and inspect them with a quick “.<TAB>”.
IPython makes reading code / docstrings a breeze - you don’t know what django.models.cheesypuff is? type “django.models.cheesypuff?” to get information and documentation about the object / method printed to your screen. That doesn’t help? then try “django.models.cheesypuff??” to get documentation AND source code. It’s brilliant.
The best bit about IPython (apart from the above and it also having access to your system shell) is that it is scriptable (in Python, of course). So all sorts of nice little tricks can be used to make life easier, one of my favourites is this little snippet. It tells IPython to automatically import any model associated with your current Django project, I’ve edited mine slightly to print the names as they’re imported so I have a nice index of the models available to me without having to traverse lots of models.py files.
In short, IPython is a fantastic tool - any work I do on querysets or databases I interactively run through in that shell first - it makes it easier to quickly catch gaps in my logic. IPython also stores all of your history (type “%history”), so you can easily copy and paste that into your editor of choice. There’s plenty I haven’t discussed (if you paste in doctests, it strips out the >>>’s allowing you to run them with a quick ctrl+v), but I’ll leave you to have a play.
What is your favourite Django debug technique?
posted by Simon Scarfe on March 3, 2008 at 8:03 a.m.
Don't forget ipdb if you have IPython installed. Makes using the debugger so much nicer.
Antti Kaihola