7.0 KiB
Coffin: Jinja2 adapter for Django
Supported Django template functionality
Coffin currently makes the following Django tags available in Jinja:
- {% cache %} - has currently an incompatibility: The second argument (the fragment name) needs to be specified with surrounding quotes if it is supposed to be a literal string, according to Jinja2 syntax. It will otherwise be considered an identifer and resolved as a variable.
- {% load %} - is actually a no-op in Coffin, since templatetag libraries are always loaded. See also "Custom Filters and extensions".
- {% spaceless %}
- {% url %} - additionally, a
"view"|url()
filter is also available. Or useview|url()
for Django 1.5 style lookups by the value ofview
. - {% with %}
- {% csrf_token %}
Django filters that are ported in Coffin:
- date
- floatformat
- pluralize (expects an optional second parameter rather than the comma syntax)
- time
- timesince
- timeuntil
- truncatewords
- truncatewords_html
Note that for the most part, you can simply use filters written for
Django directly in Coffin. For example,
django.contrib.markup
"just works" (tm).
The template-related functionality of the following contrib modules has been ported in Coffin:
coffin.contrib.syndication
.
Jinja 2's i18n
extension is hooked up with Django, and a
custom version of makemessages supports string extraction from both
Jinja2 and Django templates. Just add 'coffin' to your INSTALLED_APPS
and run makemessages as usual, specifying additional Jinja extensions if
necessary via the -e option.
Autoescape
When using Auto Escape you will notice that marking something as a Safestrings with Django will not affect the rendering in Jinja 2. To fix this you can monkeypatch Django to produce Jinja 2 compatible Safestrings:
'''Monkeypatch Django to mimic Jinja2 behaviour'''
from django.utils import safestring
if not hasattr(safestring, '__html__'):
safestring.SafeString.__html__ = lambda self: str(self)
safestring.SafeUnicode.__html__ = lambda self: unicode(self)
Rendering
Simply use the render_to_response
replacement provided
by coffin:
from coffin.shortcuts import render_to_response
render_to_response('template.html', {'var': 1})
This will render template.html
using Jinja2, and returns
a HttpResponse
.
404 and 500 handlers
To have your HTTP 404 and 500 template rendered using Jinja, replace the line:
from django.conf.urls.defaults import *
in your urls.py
(it should be there by default),
with:
from coffin.conf.urls import *
Custom filters and extensions
Coffin uses the same templatetag library approach as Django, meaning
your app has a templatetags
directory, and each of it's
modules represents a "template library", providing new filters and
tags.
A custom Library
class in
coffin.template.Library
can be used to register
Jinja-specific components.
Coffin can automatically make your existing Django filters usable in Jinja, but not your custom tags - you need to rewrite those as Jinja extensions manually.
Example for a Jinja-enabled template library:
from coffin import template
register = template.Library()
register.filter('plenk', plenk) # Filter for both Django and Jinja
register.tag('foo', do_foo) # Django version of the tag
register.tag(FooExtension) # Jinja version of the tag
register.object(my_function_name) # A global function/object
register.test(my_test_name) # A test function
You may also define additional extensions, filters, tests and globals
via your settings.py
:
JINJA2_FILTERS = (
'path.to.myfilter',
)
JINJA2_TESTS = {
'test_name': 'path.to.mytest',
}
JINJA2_EXTENSIONS = (
'jinja2.ext.do',
)
Other things of note
When porting Django functionality, Coffin currently tries to avoid Django's silent-errors approach, instead opting to be explicit. Django was discussing the same thing before it's 1.0 release (*), but was constrained by backwards-compatibility concerns. However, if you are converting your templates anyway, it might be a good opportunity for this change.
(*) http://groups.google.com/group/django-developers/browse_thread/thread/f323338045ac2e5e
coffin.template.loader
is a port of
django.template.loader
and comes with a Jinja2-enabled
version of get_template()
.
coffin.template.Template
is a Jinja2-Template that
supports the Django render interface (being passed an instance of
Context), and uses Coffin's global Jinja2 environment.
coffin.interop
exposes functionality to manually convert
Django filters to Jinja2 and vice-versa. This is also what Coffin's
Library
object uses.
A Jinja2-enabled version of add_to_builtins
can be found
in the django.template
namespace.
You may specify additional arguments to send to the
Environment
via
JINJA2_ENVIRONMENT_OPTIONS
:
from jinja2 import StrictUndefined
JINJA2_ENVIRONMENT_OPTIONS = {
'autoescape': False,
'undefined': StrictUndefined,
}
Things not supported by Coffin
These is an incomplete list things that Coffin does not yet and possibly never will, requiring manual changes on your part:
- The
slice
filter works differently in Jinja2 and Django. Replace it with Jinja's slice syntax:x[0:1]
. - Jinja2's
default
filter by itself only tests the variable for existence. To match Django's behaviour, you need to passTrue
as the second argument, so that it will also provide the default value for things that are defined but evalute toFalse
- Jinja2's loop variable is called
loop
, but Django'sforloop
. - Implementing an equivalent to Django's cycle-tag might be difficult,
see also Django tickets #5908 and #7501. Jinja's own facilities are the
forloop.cycle()
function and the global functioncycler
. - The
add
filter might not be worth being implemented.{{ x+y }}
is a pretty basic feature of Jinja2, and could almost be lumped together with the other Django->Jinja2 syntax changes. - Django-type safe strings passed through the context are not converted and therefore not recognized by Jinja2. For example, a notable place were this would occur is the HTML generation of Django Forms.
- The {% autoescape %} tag is immensily difficult to port and currently not supported.
- Literal strings from within a template are not automatically
considered "safe" by Jinja2, different from Django. According to Armin
Ronacher, this is a design limitation that will not be changed, due to
many Python builtin functions and methods, whichyou are free to use in
Jinja2, expecting raw, untainted strings and thus not being able to work
with Jinja2's
Markup
string.
Running the tests
Use the nose framework: