Tag Archives: hacks

Recursion in Django templates

Recently, someone asked in #django about outputting recursive structures, say a forum or comment thread. Although this could be considered a presentation logic issue, the smartest thing is most likely to prepare the data in your view accordingly. Besides, Django’s template language doesn’t support recursion. Or does it?

There are no macros, or a call/function concept. And if you attempt a standard recursive {% include %} you’ll notice that requests hang, as the tag is resolved during compilation – the context is still out of the picture, so there is no way to stop the recursion. But if you look at the source you’ll notice that includes are actually implemented differently if the filename is passed as a variable. A context is now needed to resolve it, and the included file is loaded while rendering (see IncludeNode vs ConstantIncludeNode).

This behavior can be exploited to solve the initial problem:

{# filename: list.html #}
{% for post in thread %}
	<li>{{ post.title }}
    {% with "list.html" as filename %}
    {% with post.replies as thread %}
        {% include filename %}
    {% endwith %}
    {% endwith %}</li>
{% endfor %}

Kind of neat, I think – although I wouldn’t recommend actually using that approach in a production app, and if it’s only for the fact that the template is reloaded from disk each and every time, which I can’t imagine is good for performance. Maybe you should use it. Doesn’t Django use a cached loader now? Make your own decision.