| Switching from other Template Engines |
| ===================================== |
| |
| .. highlight:: html+jinja |
| |
| If you have used a different template engine in the past and want to swtich |
| to Jinja2 here is a small guide that shows the basic syntatic and semantic |
| changes between some common, similar text template engines for Python. |
| |
| Jinja1 |
| ------ |
| |
| Jinja2 is mostly compatible with Jinja1 in terms of API usage and template |
| syntax. The differences between Jinja1 and 2 are explained in the following |
| list. |
| |
| API |
| ~~~ |
| |
| Loaders |
| Jinja2 uses a different loader API. Because the internal representation |
| of templates changed there is no longer support for external caching |
| systems such as memcached. The memory consumed by templates is comparable |
| with regular Python modules now and external caching doesn't give any |
| advantage. If you have used a custom loader in the past have a look at |
| the new :ref:`loader API <loaders>`. |
| |
| Loading templates from strings |
| In the past it was possible to generate templates from a string with the |
| default environment configuration by using `jinja.from_string`. Jinja2 |
| provides a :class:`Template` class that can be used to do the same, but |
| with optional additional configuration. |
| |
| Automatic unicode conversion |
| Jinja1 performed automatic conversion of bytestrings in a given encoding |
| into unicode objects. This conversion is no longer implemented as it |
| was inconsistent as most libraries are using the regular Python ASCII |
| bytestring to Unicode conversion. An application powered by Jinja2 |
| *has to* use unicode internally everywhere or make sure that Jinja2 only |
| gets unicode strings passed. |
| |
| i18n |
| Jinja1 used custom translators for internationalization. i18n is now |
| available as Jinja2 extension and uses a simpler, more gettext friendly |
| interface and has support for babel. For more details see |
| :ref:`i18n-extension`. |
| |
| Internal methods |
| Jinja1 exposed a few internal methods on the environment object such |
| as `call_function`, `get_attribute` and others. While they were marked |
| as being an internal method it was possible to override them. Jinja2 |
| doesn't have equivalent methods. |
| |
| Sandbox |
| Jinja1 was running sandbox mode by default. Few applications actually |
| used that feature so it became optional in Jinja2. For more details |
| about the sandboxed execution see :class:`SandboxedEnvironment`. |
| |
| Context |
| Jinja1 had a stacked context as storage for variables passed to the |
| environment. In Jinja2 a similar object exists but it doesn't allow |
| modifications nor is it a singleton. As inheritance is dynamic now |
| multiple context objects may exist during template evaluation. |
| |
| Filters and Tests |
| Filters and tests are regular functions now. It's no longer necessary |
| and allowed to use factory functions. |
| |
| |
| Templates |
| ~~~~~~~~~ |
| |
| Jinja2 has mostly the same syntax as Jinja1. What's different is that |
| macros require parentheses around the argument list now. |
| |
| Additionally Jinja2 allows dynamic inheritance now and dynamic includes. |
| The old helper function `rendertemplate` is gone now, `include` can be used |
| instead. Includes no longer import macros and variable assignments, for |
| that the new `import` tag is used. This concept is explained in the |
| :ref:`import` documentation. |
| |
| Another small change happened in the `for`-tag. The special loop variable |
| doesn't have a `parent` attribute, instead you have to alias the loop |
| yourself. See :ref:`accessing-the-parent-loop` for more details. |
| |
| |
| Django |
| ------ |
| |
| If you have previously worked with Django templates, you should find |
| Jinja2 very familiar. In fact, most of the syntax elements look and |
| work the same. |
| |
| However, Jinja2 provides some more syntax elements covered in the |
| documentation and some work a bit different. |
| |
| This section covers the template changes. As the API is fundamentally |
| different we won't cover it here. |
| |
| Method Calls |
| ~~~~~~~~~~~~ |
| |
| In Django method calls work implicitly. With Jinja2 you have to specify that |
| you want to call an object. Thus this Django code:: |
| |
| {% for page in user.get_created_pages %} |
| ... |
| {% endfor %} |
| |
| will look like this in Jinja:: |
| |
| {% for page in user.get_created_pages() %} |
| ... |
| {% endfor %} |
| |
| This allows you to pass variables to the function which is also used for macros |
| which is not possible in Django. |
| |
| Conditions |
| ~~~~~~~~~~ |
| |
| In Django you can use the following constructs to check for equality:: |
| |
| {% ifequal foo "bar" %} |
| ... |
| {% else %} |
| ... |
| {% endifequal %} |
| |
| In Jinja2 you can use the normal if statement in combination with operators:: |
| |
| {% if foo == 'bar' %} |
| ... |
| {% else %} |
| ... |
| {% endif %} |
| |
| You can also have multiple elif branches in your template:: |
| |
| {% if something %} |
| ... |
| {% elif otherthing %} |
| ... |
| {% elif foothing %} |
| ... |
| {% else %} |
| ... |
| {% endif %} |
| |
| Filter Arguments |
| ~~~~~~~~~~~~~~~~ |
| |
| Jinja2 provides more than one argument for filters. Also the syntax for |
| argument passing is different. A template that looks like this in Django:: |
| |
| {{ items|join:", " }} |
| |
| looks like this in Jinja2:: |
| |
| {{ items|join(', ') }} |
| |
| In fact it's a bit more verbose but it allows different types of arguments - |
| including variables - and more than one of them. |
| |
| Tests |
| ~~~~~ |
| |
| In addition to filters there also are tests you can perform using the is |
| operator. Here are some examples:: |
| |
| {% if user.user_id is odd %} |
| {{ user.username|e }} is odd |
| {% else %} |
| hmm. {{ user.username|e }} looks pretty normal |
| {% endif %} |
| |
| Loops |
| ~~~~~ |
| |
| For loops work very similar to Django, the only incompatibility is that in |
| Jinja2 the special variable for the loop context is called `loop` and not |
| `forloop` like in Django. |
| |
| Cycle |
| ~~~~~ |
| |
| The ``{% cycle %}`` tag does not exist in Jinja because of it's implicit |
| nature. However you can achieve mostly the same by using the `cycle` |
| method on a loop object. |
| |
| The following Django template:: |
| |
| {% for user in users %} |
| <li class="{% cycle 'odd' 'even' %}">{{ user }}</li> |
| {% endfor %} |
| |
| Would look like this in Jinja:: |
| |
| {% for user in users %} |
| <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li> |
| {% endfor %} |
| |
| There is no equivalent of ``{% cycle ... as variable %}``. |
| |
| |
| Mako |
| ---- |
| |
| .. highlight:: html+mako |
| |
| If you have used Mako so far and want to switch to Jinja2 you can configure |
| Jinja2 to look more like Mako: |
| |
| .. sourcecode:: python |
| |
| env = Environment('<%', '%>', '${', '}', '%') |
| |
| Once the environment is configure like that Jinja2 should be able to interpret |
| a small subset of Mako templates. Jinja2 does not support embedded Python code |
| so you would have to move that out of the template. The syntax for defs (in |
| Jinja2 defs are called macros) and template inheritance is different too. The |
| following Mako template:: |
| |
| <%inherit file="layout.html" /> |
| <%def name="title()">Page Title</%def> |
| <ul> |
| % for item in list: |
| <li>${item}</li> |
| % endfor |
| </ul> |
| |
| Looks like this in Jinja2 with the above configuration:: |
| |
| <% extends "layout.html" %> |
| <% block title %>Page Title<% endblock %> |
| <% block body %> |
| <ul> |
| % for item in list: |
| <li>${item}</li> |
| % endfor |
| </ul> |
| <% endblock %> |