cra
mr

Using Jinja With Django

You're viewing an archived post which may have broken links or images. If this post was valuable and you'd like me to restore it, let me know!

Every time I meet someone new who asks me about Django, I tell them exactly what I think. It’s a great product. It does exactly what it’s designed to do. Allows you to build decently structured applications rapidly, without much overhead in doing so. One of the other things I tell them, is that the first they should do is scrap the template engine, and install Jinja.

Jinja is a sandboxed template engine, written in Python of course. It’s created by the guys over at Pocoo. It has a number of improvements over the Django engine, including faster rendering. Most of all, it allows you to place logic in templates where you need to, when Django does not.

Core Differences

Jinja templates are not 100% compatible with Django, and vice versa. Some of the biggest changes include methods required parenthesis, being able to access and pass attributes marked as pseudo-private (e.g. instance._meta), and a number of additional types of calls in templates. You will also find that all keywords are lowercase, those being true, false, none, and undefined. Best of all, you can use else if and any operator inside your if clauses just like you can in Python. No more clustered lists of `{% if %}{% if %}{% ifnotequal %}`.

Jinja

{% extends "bone/bone.html" %}

{% block content %} <h1>My Objects</h1> {% for object in myobjects.iteritems() %} <li class=”{% cycle ‘row1’,‘row2’,‘row3’,‘row4’ %}”><a href=”{{ object.getabsolute_url }}”>{{ object.name|escape }}</a><br /></li>{% endfor %} {% endblock %}

Django

{% extends "bone/bone.html" %}

{% block content %} <h1>My Objects</h1> <ul> {% for object in myobjects.iteritems %} <li class=”{% cycle row1 row2 %}”><a href=”{{ object.getabsolute_url }}”>{{ object.name|escape }}</a><br /></li> {% endfor %} {% endblock %}

As you can see from the example above, the code is almost identical. Again, the main difference being how you access methods. You’ll also notice the cycle example I included, which can take any number of arguments, but you must also pass variables. Jinja doesn’t assume everything is a string as Django does.

Update: It seems Django (since a few months) supports multiple strings in the cycle like Jinja. Django also now supports auto-escaping, so the |escape would be invalid in the Django example (unless you did &#123;% autoescape off %&#125;).

Filters and Template Tags

One of my favorite features in Jinja are the filters and template tags. It provides a lot of useful filters, such as `capture` and filters are also much more flexible than they are in Django. Jinja filters and template tags are also all loaded into memory initially. There is no need to use `{% load library %}`. You can also set variables within your template if you want to optimize things, with `{% set varname = value %}`.

Another feature with you’ll find in Jinja are tests. Tests are simply that, a test on an element. Some common tests include even, odd, and sameas. Tests are used in the form of varname is test [optional arguments]. These can be used both within if statements, and variable calls.

Installing Jinja

Jinja has been made pretty easy to install with Django. While this might change (a bit) if I have my way, it still works fairly well with a little bit of magic. So to begin the install, you first need to the grab the package. I recommend getting trunk, via setuptools, using `easy_install Jinja==dev`. Once you've installed Jinja, you're going to want to include a few lines at the bottom of `settings.py`. ```python # Initialize django.contrib.jinja from jinja.contrib import djangosupport djangosupport.configure() ```

These lines perform a little magic in the backend. They allow you to import Jinja from django.contrib.jinja, and include some conversion tools for Django template filters.

To use Jinja within your page, you then need to from django.contrib.jinja import render_to_response, render_to_string. I haven’t used Django’s template engine in almost two years, so the syntax may not match, so here’s an example:

def myview(request):
    return render_to_response('mytemplate.html', request=request)

def myotherview(request):
    context = {'myvar': True}
    return render_to_response('mytemplate.html', context, request)

The request and context variables are completely optionally. If you pass request it will cause your context processors to render.

Converting Django Filters

Due to Jinja not implementing nearly as many defaults (most are edge cases, this is a design decision), converting Django filters is stupidly simple in Jinja. You first need to import the conversion function, and the registration function:
from django.contrib.jinja import register, convert_django_filter

Once our functions are available, the rest is easy:

# Import the filter we want to convert
from django.template.defaultfilters import floatformat

# Register the converted filter.
register.filter(convert_django_filter(floatformat), 'floatformat')

Simple, right? Now you just need to make sure this file gets imported somehow on initialization. The easiest way is to create a utilities app, or something similar, and load them there. E.g. myproject.template.filters. You’ll then need to place this inside of your INSTALLED_APPS setting.

Wrap Us

If you're not convinced yet, or you want to learn more, head over to the [Jinja website](http://jinja.pocoo.org) and [read the documentation](http://jinja.pocoo.org/documentation/). ```