Blog

The Digital Agency for International Development

Embedding jinja2 templates in Django templates

By Martin Burchell on 15 November 2011

We recently integrated the Askbot forum into the Django-based websites we developed for the RIMI4AC Project. Askbot uses the Jinja2 templating language but this was incompatible with the standard Django templates we had used up to this point. Here's how we solved the problem.

When we were asked to recommend a forum to be integrated into the suite of websites we were developing for the RIMI4AC Project, Askbot was the clear favourite, due to its large feature set, ease of customisation, active development team and wide user base. The only drawback was that the templating engine used by Askbot was Jinja2, which would make it difficult for Askbot to be embedded into the websites. Up until then these websites had been developed using standard Django templates.

We came up with the following options to solve this problem:

Create an Askbot skin using Jinja2, which would mimic our existing templates

This would be easy to implement but would incur high maintenance costs, as any changes to the standard Django templates would need to be made also to the Jinja2 templates. This could possibly be scripted to make this easier.

Embed Askbot in an iframe

Again this would be simple to implement but iframes introduce a number of problems themselves with navigation and rendering.

Rewrite Askbot to use Django templates

This would be a lot of work and as we would effectively be forking Askbot we would incur the costs of maintaining our own version.

Rewrite the rest of our websites to use Jinja2 templates

This would be quite a bit of work and any new components we wanted to integrate into our websites would also need to use Jinja2.

Choose a different forum that used Django templates

We really didn't want to do this as we had had good reasons for choosing Askbot.

Some way of rendering Django templates from within Jinja2

Although Jinja2 supports extensions and we could possibly have written one to render Django templates, this seemed to be the opposite of what we wanted - to embed Askbot as a component of our website and not the other way around.

Some way of rendering Jinja2 templates from within Django templates

This looked like the most promising solution. Fortunately the Askbot developers were good enough to name their views, which meant that we could provide our own urls.py with views of the same name and then any reverse() lookups within Askbot would just work. Any view that rendered into a Jinja2 template by calling the function render_into_skin() would be replaced with this wrapper function:

def render_jinja2_into_django_template(request, jinja2_view, *args, **kwargs):
    response = jinja2_view(request, *args, **kwargs)

return render_to_response("forum_container.html", {'forum_content':response.content}, context_instance=RequestContext(request))

The wrapper function would call the original Jinja2 view function and we could pull the raw content out of the returned response object. This would go into the forum_content variable that would be passed to our own Django template and simply written out from within there.

Because we wanted Askbot to appear as a component within a page rather than its own standalone application, we would also need to remove the headers and footers from the Askbot Jinja2 templates. Askbot's skin customisation made this straightforward. The Django container template would need to include any stylesheets or scripts that we had removed from the headers.

With some fixes to the CSS we had successfully embedded Askbot in our website. There would be some maintenance costs in that any future changes to the Askbot views would need to be reflected in our own Askbot views, but this would be far preferable to having to maintain our own set of templates.