Django template tags within Jinja2

In some cases it can be useful to enable Django tags within your Jinja2 templates, for example… when you are converting your templates but still have some legacy tags/filters that don’t support Jinja2 or if you are using a project without Jinja2 support.

Luckily, that’s not too difficult to achieve with Jinja2, actually a lot easier than the reverse as discussed in http://w.wol.ph/2013/07/28/mixing-django-with-jinja2-without-losing-template-debugging/

It should be noted that the Coffin library is used in this example but these imports could easily be replaced with straight up Jinja2.

The actual code:

from django import template as django_template
from jinja2 import nodes, contextfunction, ext
from coffin.template import Library, Template


# Create a Library to register the tags
register = Library()


# The actual Django templatag for Jinja
class Django(ext.Extension):
    tags = set(['django'])

    def preprocess(self, source, name, filename=None):
        source = source.replace('{% django %}', '{% django %}{% raw %}')
        source = source.replace('{% enddjango %}',
            '{% endraw %}{% enddjango %}')
        return source

    def parse(self, parser):
        lineno = parser.stream.next().lineno

        while not parser.stream.next().test('block_end'):
            pass

        body = nodes.Const(parser.stream.next().value)

        while not parser.stream.current.test('block_end'):
            parser.stream.next()

        return nodes.Output([
            self.call_method('_django', args=[body], kwargs=[]),
        ]).set_lineno(lineno=lineno)

    @contextfunction
    def _django(self, context, html):
        return django(context, html)

# Registering the tag
register.tag(Django)


# Alternatively, we can also call `django()` as a function.
# Our templatetag silently converts the Django tag to this function call
@contextfunction
@register.object
def django(context, html):
    context = django_template.RequestContext(context['request'], context)
    return django_template.Template(html).render(context)

Now the tag can be used like this:

{% if foo == bar %}
Jinja style if...
{% endif %}

{% django %}
{% ifequal foo bar %}
Django style if...
{% endif %}
{% enddjango %}
Bookmark and Share

About Rick van Hattem

Rick van Hattem is a Dutch Internet entrepreneur and co-founder of Fashiolista.com
No comments yet.

Leave a Reply