Jinja2 and Django 4ever
My goal is to stop hating Django. Our team has been bouncing back and forth between using Django and Pylons for the creation of the web front end for ChompStack, a restaurant-oriented iPhone app site with an admin panel for easy data management.
In the beginning, there was Django, and it was good. But gradually we began to find its paradigms counterintuitive: we disliked the idea of apps and considered the built-in template language pretty crippled. More importantly, we prefer the epically powerful SQLAlchemy to Django’s ORM of Doom, so with the evidence before us, we switched to Pylons and the haven of SQLAlchemy/Jinja, only to discover we had switched from a shitty apartment in Brooklyn to a tent in the desert. No cockroaches, true, but no running water, either. Who really wants to write a thumbnail library? (Apologies to anyone who has actually written a thumbnail library)
So now we’re back to Django, but we’re using the 1.2 development version, and we’re taking Jinja2 with us. Here’s how:
- Install Jinja2.
- Integrate Jinja2 with Django
- Test your monster.
sudo easy_install jinja2
Create a Django project if you haven’t already. The name of my test project is jinja_replace. Now create a file in a location which can be imported. For example, I created a lib directory, added the requisite __init__.py file, and then created a jinja2django.py file. You could put this file anywhere accessible to your project.
Most of the following code is derived from this excellent Django snippet, which you should certainly check out. My version is just a little simpler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from django.http import HttpResponse from django.conf import settings from jinja2 import Environment, ChoiceLoader, FileSystemLoader # Setup environment default_mimetype = getattr(settings, 'DEFAULT_CONTENT_TYPE') # Create the Jinja2 Environment env = Environment( line_statement_prefix='%', line_comment_prefix='##', loader=ChoiceLoader([FileSystemLoader(path) for path in getattr(settings, 'TEMPLATE_DIRS', ())]) ) def render_to_string(filename, context={}): return env.get_template(filename).render(**context) def render_to_response(filename, context={},mimetype=default_mimetype, request = None): if request: context['request'] = request return HttpResponse(render_to_string(filename, context),mimetype=mimetype) |
Two things to note here. One, we’re really only replacing two functions: render_to_string and render_to_response, which calls render_to_string. Two, Jinja requires us to create an environment object, and we do this at the module level. The environment object is responsible for retrieving the template. We’re doing something kind of neat with the environment configuration by setting the line_statement_prefix and line_comment_prefix to something other than the default. This allows us to use Jinja2 in this fashion, replacing the usual {% block %} notation:
1 2 3 4 5 6 7 8 9 10 | % block container
% include "header.html"
<div id="main">
% for message in messages:
<div class="message success">
<h2>Congratulations</h2>
<p>{{ message }}</p>
</div>
% endfor
</div> |
Now that we’re cool like that, we need to complete just two more steps to get this puzzle together. Go to whatever views.py file you’ve created which will be rendering your Jinja2 templates, and instead of using the standard Django render_to_response shortcut, import your custom render_to_response method. My views.py looks like this:
1 2 3 4 | from jinja_replace.lib.jinja2django import render_to_response def index(request): return render_to_response("index.html", context={"name":"Steve"}) |
Finally, create your template. I put mine in a templates directory in my main project, then went to my settings.py file and added that templates dir as such:
import os
ROOT_PATH = os.path.dirname(__file__)
TEMPLATE_DIRS = (
os.path.join(ROOT_PATH,'templates'),
)
And here’s my templates/index.html (super complex, I know…try to keep up):
1 | Welcome to Hindsight Labs, {{ name }}! |
-
http://www.rosslawley.co.uk Ross
-
Christine Meranda
-
http://hostomato.com/ Olav
-
Christine Meranda