summaryrefslogtreecommitdiffstats
path: root/docs/switching.rst
blob: caa35c36821cd8a0cc9e4b8368286a578d4021d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
Switching From Other Template Engines
=====================================

This is a brief guide on some of the differences between Jinja syntax
and other template languages. See :doc:`/templates` for a comprehensive
guide to Jinja syntax and features.


Django
------

If you have previously worked with Django templates, you should find
Jinja very familiar. Many of the syntax elements look and work the same.
However, Jinja provides some more syntax elements, and some work a bit
differently.

This section covers the template changes. The API, including extension
support, is fundamentally different so it won't be covered here.

Django supports using Jinja as its template engine, see
https://docs.djangoproject.com/en/stable/topics/templates/#support-for-template-engines.


Method Calls
~~~~~~~~~~~~

In Django, methods are called implicitly, without parentheses.

.. code-block:: django

    {% for page in user.get_created_pages %}
        ...
    {% endfor %}

In Jinja, using parentheses is required for calls, like in Python. This
allows you to pass variables to the method, which is not possible
in Django. This syntax is also used for calling macros.

.. code-block:: jinja

    {% for page in user.get_created_pages() %}
        ...
    {% endfor %}


Filter Arguments
~~~~~~~~~~~~~~~~

In Django, one literal value can be passed to a filter after a colon.

.. code-block:: django

    {{ items|join:", " }}

In Jinja, filters can take any number of positional and keyword
arguments in parentheses, like function calls. Arguments can also be
variables instead of literal values.

.. code-block:: jinja

    {{ items|join(", ") }}


Tests
~~~~~

In addition to filters, Jinja also has "tests" used with the ``is``
operator. This operator is not the same as the Python operator.

.. code-block:: jinja

    {% if user.user_id is odd %}
        {{ user.username|e }} is odd
    {% else %}
        hmm. {{ user.username|e }} looks pretty normal
    {% endif %}

Loops
~~~~~

In Django, the special variable for the loop context is called
``forloop``, and the ``empty`` is used for no loop items.

.. code-block:: django

    {% for item in items %}
        {{ item }}
    {% empty %}
        No items!
    {% endfor %}

In Jinja, the special variable for the loop context is called ``loop``,
and the ``else`` block is used for no loop items.

.. code-block:: jinja

    {% for item in items %}
        {{ loop.index}}. {{ item }}
    {% else %}
        No items!
    {% endfor %}


Cycle
~~~~~

In Django, the ``{% cycle %}`` can be used in a for loop to alternate
between values per loop.

.. code-block:: django

    {% for user in users %}
        <li class="{% cycle 'odd' 'even' %}">{{ user }}</li>
    {% endfor %}

In Jinja, the ``loop`` context has a ``cycle`` method.

.. code-block:: jinja

    {% for user in users %}
        <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
    {% endfor %}

A cycler can also be assigned to a variable and used outside or across
loops with the ``cycle()`` global function.


Mako
----

You can configure Jinja to look more like Mako:

.. code-block:: python

    env = Environment(
        block_start_string="<%",
        block_end_string="%>",
        variable_start_string="${",
        variable_end_string="}",
        comment_start_string="<%doc>",
        commend_end_string="</%doc>",
        line_statement_prefix="%",
        line_comment_prefix="##",
    )

With an environment configured like that, Jinja should be able to
interpret a small subset of Mako templates without any changes.

Jinja does not support embedded Python code, so you would have to move
that out of the template. You could either process the data with the
same code before rendering, or add a global function or filter to the
Jinja environment.

The syntax for defs (which are called macros in Jinja) and template
inheritance is different too.

The following Mako template:

.. code-block:: mako

    <%inherit file="layout.html" />
    <%def name="title()">Page Title</%def>
    <ul>
    % for item in list:
        <li>${item}</li>
    % endfor
    </ul>

Looks like this in Jinja with the above configuration:

.. code-block:: jinja

    <% extends "layout.html" %>
    <% block title %>Page Title<% endblock %>
    <% block body %>
    <ul>
    % for item in list:
        <li>${item}</li>
    % endfor
    </ul>
    <% endblock %>