Some Simple Django Debugging Tools
Before you can debug a problem, sometimes before you even know a problem exists, you have to be able to work out what is going on. In many cases, this means somehow capturing the state of the system. Although most people encounter the odd Heisen-bug — a problem that seems to mysteriously vanish whenever you try to observe it — they aren't the common case.
There are a few little items that come with Django, right out of the box, which are not as well known as they might be. I don't always use these, but, at various times, they each play the role of right tool for the job. Nothing too deep here; I'm aiming only to put a few ideas into people's heads.
The general theme is using the template system to display some debugging information. Sometimes I feel that people try to debug problems that aren't template related through the browser a bit too readily (and then they wonder why it's difficult). Part of debugging is removing any unnecessary components, after all. If you're debugging template-level problems, however, these might be useful.
Debug Context Processor
The debug context processor isn't enabled by default, but it's sometimes worth using. Two uses here:
- Showing all the SQL statements used to construct the page.
- Making a context variable (
debug
) available to indicate when the debug setting is enabled, which can be used to trigger the display of other information of your own design.
When I've gotten the basic structure of a site together, I'll enable this context processor and start to look at the SQL that's being generated. A few easy optimisations often show up. My own approach for displaying the information is to use the following fragment just before the </html>
part of the base template:
{% if debug %}<!-- SQL queries ({{ sql_queries|length }}): {% for query in sql_queries %} {{ query.sql|safe|wordwrap:"75" }} ({{ query.time }}) {% endfor %} -->{% endif %}
The SQL queries are dumped into an HTML comment, formatted with linebreaks so that they display nicely in a standard "view source" window (I don't want to have to keep messing around with enabling line wrapping or whatever).
The "pprint" Template Filter
If you're dumping any raw (or basically unformatted) Python structure into a template for debugging, it will often turn out looking pretty ugly. Being able to read the Python data is as important as being able to display it. Be nice to your eyes, since this is often only the first step of a long process.
Enter the pprint template filter. It passes the contents of the variable it is filtering through Python's pprint()
. That will introduce some useful linebreaks and horizontal spacing into the results. Since HTML rendering normally ignores such things, we have to wrap the output display in pre
tags as well:
<pre>{{ python_structure|pprint }}</pre>
Django's auto-escaping behaviour will also play a role here. Any "<"
characters, for example, will automatically be turned into "<"
entities, so they will display as the right character in the rendered result, instead of being interpreted as HTML.
The "debug" Template Tag
Sometimes you just want to know what is contained in the template's context, particularly when something isn't rendering as expected. You want to check if the necessary information is not present at all, or being used incorrectly.
The debug template tag does this. It displays the templates context (the set of variables available for use in the template), as well as the current sys.modules
contents.
As with the pprint
filter, if the result is to be displayed in an HTML page, we need to use <pre>...</pre>
tags to make things display nicely (the debug tag uses Python's pprint
module internally to generate raw formatted output). Since debug
is a template tag, not a filter, the output isn't automatically run through the auto-escaping process. As it's not always used in HTML (not all templates are HTML output), the debug tag doesn't produce pre-escaped HTML. So we have to escape the results ourself:
<pre>{% filter force_escape %}{% debug %}{% endfilter %}</pre>
Maybe not as simple as I'd like — it gets a bit tiring having to remember all the extra bits to wrap around the tag — but it's not too onerous and the slight clunkiness is because it also works in non-HTML environments, which is a benefit.
I must admit, I don't find myself using the debug
tag very often. Normally, if I want to see what variables are available in the context, I'll add debugging to the appropriate view. Sometimes, though, it's a small push in the right direction. One place I do find it useful is in conjunction with the direct_to_template()
view, which is the next tool in the box.
The "direct_to_template" View
This generic view is useful in many ways and it's worth remembering it exists. It's a nice shortcut for rendering a static template, with access to any parameters that might have come in through the URL. All the URL parameters are put into a dictionary called params
, which is passed into the template (the context variable is called "params", that is).
When I'm just fleshing out an application and want to stub out some URLs, I'll sometimes create a simple template that looks something like this:
{% extends "base.html" %} {% block main_content %} <pre>{% filter force_escape %}{% debug %}{% endfilter %}</pre> {% endblock %}
This template can be used over and over again as a target for URL patterns. Suppose it's called "dump_input.html". A URL Conf entry might look like:
urlpatterns = patterns('', url("^help/(?P<help>\w+)/$", direct_to_template, name="help"), ... )
When I'm developing such a site, I can refer to "/help/foo/"
and nothing will break. The page won't be finished, but it will look like the rest of the site — I extended the "base.html" template for that reason — and show which help topic is being requested.
The Debug Toolbar
This the only component mentioned here that isn't part of Django itself. It's a useful extension written by Rob Hudson and available here (if you don't use git, you can still click the "download" link to get a tarball or zipfile snapshot). There are a couple of forks for this code around, even on github itself, but Rob seems to be pulling in most of the major changes, so I'll treat his as the main version for my purposes here.
The debug toolbar is a more invasive look at what went into creating a particular page (in the sense that it has both client-side and server-side pieces to collect all the information). It's still work in progress, but Rob seems to take all sensible patches quite readily. If you're like me and don't have monitor that is 2 metres wide and 6.5 billion pixels across (which I believe is standard for those who've sold their soul to the Church Of Mac these days), there are some layout issues. One day I'm hoping to have enough free time to poke at the Javascript (it's jQuery based) and make it scale a bit better to the screen size. More hopefully, though, somebody else will get there first.
In any case, if you're trying to look at things beyond basic functionality problems, the debug-toolbar is probably a good next step. The tools I've mentioned in the previous section are more useful for getting the basic rendering working, whilst the debug-toolbar is more for inspecting things like the number of queries made and other server-side computations. Possibly it would have been better named the introspection-toolbar. Still, we all know that naming is one of the hard areas of Computer Science.