Convert Django Templates to Jinja2

From splike.com
Jump to: navigation, search

If you're switching from Django syntax templates to using Jinja2 templates within Django, you'll need to know more than the docs say about it.

Syntax changes

DjangoJinja2

some_array|join:", "

some_array|join(", ")

{% ifequal a b %} ... {% endifequal %}

{% if a == b %} ... {% endif %}

{% comment %} ... {% endcomment %}

{# ... #}
(plus it can surround other {% %} tags)

{% url project.views.show_something foo "bar" 12 %}

{{ "project.views.show_something"|url(foo, "bar", 12)}
(need 'url' filter from http://www.djangosnippets.org/snippets/1062/)

foo.items
(django would automatically invoke functions)

foo.items()
(else you'll get 'builtin_function_or_method' object is not iterable


Settings

Django has autoescape on by default, but Jinja2 has it off by default. To turn it on, add autoescape=True to your Environment() constructor

The way django marks forms and other "standard" html generating entities as "safe" from auto-escaping is not picked up by Jinja2, so you'll have to use the |safe filter on it explicitly.

Filters

Jinja2 comes with many filters.

You can re-use django filters in jinja2. For example, you could add these to your Jinja2 filter list:

'django.template.defaultfilters.linebreaks',
'django.template.defaultfilters.linebreaksbr',

http://www.djangosnippets.org/snippets/1062/ has some nice filters. http://www.djangosnippets.org/snippets/1371/ has a few more.

Setup

Take a look at http://www.djangosnippets.org/snippets/1061/ and perhaps the context chaining from http://bitbucket.org/mitsuhiko/jinja2-main/src/c07588cf115f/ext/djangojinja2.py to reuse some of your existing Django settings, etc.

Playing "nice" together

You can make a template that works in both Jinja2 and Django (for example if you have a master.html that is extended by both Jinja2 and Django). First, you have to limite your conditionals to {% if SOME_BOOLEAN %}. No comparisons, equality checks, etc. So you may have to make lots of context globals.

If you want to have some code that only renders in Jinja2 and Django skips it, you can do this:

<span style="display:none">{# </span>
{%comment%} This is an ugly way to get the contained content to only run when processed by jinja2 and not by django
#}</span>

{% some.method('call') %} 
{# or other jinja2-specific tags and filters #}

<span>
{# <span>
{%endcomment%}
<span style="display:none">#}</span>

Kicking Django templates out of 404/500 pages and 3rd-party apps

You have to monkey-patch django.template.loader.get_loader so that all template renderings can go through Jinja2 if you want. Smorgasbord is a little module to do just that for Jinja2 and 3 other templating languages. But I found that it wasn't possible to reuse an existing Jinja2 Environment object, nor could you add your own filters to the Environment object it made. So I wrote http://www.djangosnippets.org/snippets/1370/ to re-use an existing Environment object.