| ====================== |
| Designer Documentation |
| ====================== |
| |
| This part of the Jinja documentaton is meant for template designers. |
| |
| Basics |
| ====== |
| |
| The Jinja template language is designed to strike a balance between content |
| and application logic. Nevertheless you can use a python like statement |
| language. You don't have to know how Python works to create Jinja templates, |
| but if you know it you can use some additional statements you may know from |
| Python. |
| |
| Here is a small example template: |
| |
| .. sourcecode:: html+jinja |
| |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> |
| <head> |
| <title>My Webpage</title> |
| </head> |
| <body> |
| <ul id="navigation"> |
| {% for item in navigation %} |
| <li><a href="{{ item.href|e }}">{{ item.caption|e }}</a></li> |
| {% endfor %} |
| </ul> |
| |
| <h1>My Webpage</h1> |
| {{ variable }} |
| </body> |
| </html> |
| |
| This covers the default settings. The application developer might have changed |
| the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar. This |
| documentation just covers the default values. |
| |
| A variable looks like ``{{ foobar }}`` where foobar is the variable name. Inside |
| of statements (``{% some content here %}``) variables are just normal names |
| without the braces around it. In fact ``{{ foobar }}`` is just an alias for |
| the statement ``{% print foobar %}``. |
| |
| Variables are coming from the context provided by the application. Normally there |
| should be a documentation regarding the context contents but if you want to know |
| the content of the current context, you can add this to your template: |
| |
| .. sourcecode:: html+jinja |
| |
| <pre>{{ debug()|e }}</pre> |
| |
| A context isn't flat which means that each variable can has subvariables, as long |
| as it is representable as python data structure. You can access attributes of |
| a variable using the dot and bracket operators. The following examples show |
| this: |
| |
| .. sourcecode:: jinja |
| |
| {{ user.username }} |
| is the same as |
| {{ user['username'] }} |
| you can also use a variable to access an attribute: |
| {{ users[current_user].username }} |
| If you have numerical indices you have to use the [] syntax: |
| {{ users[0].username }} |
| |
| *new in Jinja 1.2*: You can now use django like attributes for integer |
| indices. Thus ``{{ foo.0 }}`` is equivalent to ``{{ foo[0] }}``. |
| |
| |
| Loops |
| ===== |
| |
| To iterate over a sequence, you can use the `for` loop. It basically looks like a |
| normal Python `for` loop and works pretty much the same: |
| |
| .. sourcecode:: html+jinja |
| |
| <h1>Members</h1> |
| <ul> |
| {% for user in users %} |
| <li>{{ loop.index }} / {{ loop.length }} - {{ user.username|escape }}</li> |
| {% else %} |
| <li><em>no users found</em></li> |
| {% endfor %} |
| </ul> |
| |
| *Important* Contrary to Python is the optional `else` block only |
| executed if there was no iteration because the sequence was empty. |
| |
| Inside of a `for` loop block you can access some special variables: |
| |
| +----------------------+----------------------------------------+ |
| | Variable | Description | |
| +======================+========================================+ |
| | `loop.index` | The current iteration of the loop. | |
| +----------------------+----------------------------------------+ |
| | `loop.index0` | The current iteration of the loop, | |
| | | starting counting by 0. | |
| +----------------------+----------------------------------------+ |
| | `loop.revindex` | The number of iterations from the end | |
| | | of the loop. | |
| +----------------------+----------------------------------------+ |
| | `loop.revindex0` | The number of iterations from the end | |
| | | of the loop, starting counting by 0. | |
| +----------------------+----------------------------------------+ |
| | `loop.first` | True if first iteration. | |
| +----------------------+----------------------------------------+ |
| | `loop.last` | True if last iteration. | |
| +----------------------+----------------------------------------+ |
| | `loop.even` | True if current iteration is even. | |
| +----------------------+----------------------------------------+ |
| | `loop.odd` | True if current iteration is odd. | |
| +----------------------+----------------------------------------+ |
| | `loop.length` | Total number of items in the sequence. | |
| +----------------------+----------------------------------------+ |
| | `loop.parent` | The context of the parent loop. | |
| +----------------------+----------------------------------------+ |
| |
| Loops also support recursion. Let's assume you have a sitemap where each item |
| might have a number of child items. A template for that could look like this: |
| |
| .. sourcecode:: html+jinja |
| |
| <h1>Sitemap |
| <ul id="sitemap"> |
| {% for item in sitemap recursive %} |
| <li><a href="{{ item.url|e }}">{{ item.title|e }}</a> |
| {% if item.children %}<ul>{{ loop(item.children) }}</ul>{% endif %}</li> |
| {% endfor %} |
| </ul> |
| |
| What happens here? Basically the first thing that is different to a normal |
| loop is the additional ``recursive`` modifier in the `for`-loop declaration. |
| It tells the template engine that we want recursion. If recursion is enabled |
| the special `loop` variable is callable. If you call it with a sequence it will |
| automatically render the loop at that position with the new sequence as argument. |
| |
| Cycling |
| ======= |
| |
| Sometimes you might want to have different text snippets for each row in a list, |
| for example to have alternating row colors. You can easily do this by using the |
| ``{% cycle %}`` tag: |
| |
| .. sourcecode:: html+jinja |
| |
| <ul id="messages"> |
| {% for message in messages %} |
| <li class="{% cycle 'row1', 'row2' %}">{{ message|e }}</li> |
| {% endfor %} |
| </ul> |
| |
| Each time Jinja encounters a `cycle` tag it will cycle through the list |
| of given items and return the next one. If you pass it one item jinja assumes |
| that this item is a sequence from the context and uses this: |
| |
| .. sourcecode:: html+jinja |
| |
| <li style="color: {% cycle rowcolors %}">...</li> |
| |
| Conditions |
| ========== |
| |
| Jinja supports Python-like `if` / `elif` / `else` constructs: |
| |
| .. sourcecode:: jinja |
| |
| {% if user.active %} |
| user {{ user.name|e }} is active. |
| {% elif user.deleted %} |
| user {{ user.name|e }} was deleted some time ago. |
| {% else %} |
| i don't know what's wrong with {{ user.username|e }} |
| {% endif %} |
| |
| If the user is active the first block is rendered. If not and the user was |
| deleted the second one, in all other cases the third one. |
| |
| You can also use comparison operators: |
| |
| .. sourcecode:: html+jinja |
| |
| {% if amount < 0 %} |
| <span style="color: red">{{ amount }}</span> |
| {% else %} |
| <span style="color: black">{{ amount }}</span> |
| {% endif %} |
| |
| .. admonition:: Note |
| |
| Of course you can use `or` / `and` and parentheses to create more complex |
| conditions, but usually the logic is already handled in the application and |
| you don't have to create such complex constructs in the template code. However |
| in some situations it might be a good thing to have the abilities to create |
| them. |
| |
| Literals |
| ======== |
| |
| For most of the builtin python types, literals exist in Jinja. The following |
| table shows which syntax elements are supported: |
| |
| ======================= =================================================== |
| ``"text" / 'text'`` work like python's unicode literals (u'text'). |
| ``42`` integer literls. |
| ``42.0`` float literals (exponents are not supported and |
| before and after the dot digits must be present) |
| ``[1, 'two', none]`` list literal |
| ``(), (1,), (1, 2)`` tuple literals. (tuples work like lists but consume |
| less memory and are not modifyable.) |
| ``{'foo': 'bar'}`` dictionary literal |
| ``@/expr/flags`` regular expression literals. ``@/expr/flags`` is |
| equivalent to ``re.compile('(?flags)expr')`` in |
| python. |
| ``@(1, 2, 3)`` set literal. ``@(1, 2, 3)`` in Jinja is is equal to |
| ``set([1, 2, 3])`` in python. |
| ``true / false`` corresponds to `True` and `False` in python. |
| ``none`` corresponds to `None` in python. |
| ``undefined`` special Jinja undefined singleton. |
| ======================= =================================================== |
| |
| .. admonition:: Common Pitfalls |
| |
| Keep in mind that Jinja literals, keywords and functions are all lowercase. |
| If you're used to Python you probably tried to write `True` which evaluates |
| to undefined because it simply does not exist. The correct name for the |
| true value is just `true` (lowercase). |
| |
| |
| Operators |
| ========= |
| |
| Inside ``{{ variable }}`` blocks, `if` conditions and many other parts you can |
| can use expressions. In expressions you can use any of the following operators: |
| |
| ======= =================================================================== |
| ``+`` add the right operand to the left one. |
| ``{{ 1 + 2 }}`` would return ``3``. |
| ``-`` subtract the right operand from the left one. |
| ``{{ 1 - 1 }}`` would return ``0``. |
| ``/`` divide the left operand by the right one. |
| ``{{ 1 / 2 }}`` would return ``0.5``. |
| ``//`` divide the left operand by the right one and return a truncated |
| integer result: ``{{ 20 // 7 }}`` is ``2``. |
| *added in Jinja 1.1* |
| ``~`` string concatenate a value with another one. ``{{ foo ~ bar }}`` |
| is equivalent to ``{{ foo|string + bar|string }}``. *added in |
| Jinja 1.1* |
| ``*`` multiply the left operand with the right one. |
| ``{{ 2 * 2 }}`` would return ``4``. |
| ``**`` raise the left operand to the power of the right |
| operand. ``{{ 2**3 }}`` would return ``8``. |
| ``%`` calculate the remainder of an integer division between the |
| left and right operand: ``{{ 11 % 7 }}`` is ``4``. |
| ``in`` perform sequence membership test. ``{{ 1 in [1,2,3] }}`` would |
| return true. |
| ``is`` perform a test on the value. See the section about |
| tests for more information. |
| ``|`` apply a filter on the value. See the section about |
| filters for more information. |
| ``and`` return true if the left and the right operand is true. |
| ``or`` return true if the left or the right operand is true. |
| ``not`` negate a statement (see below) |
| ``()`` call a callable: ``{{ user.get_username() }}``. Inside of the |
| parentheses you can use variables: ``{{ user.get(username) }}``. |
| ======= =================================================================== |
| |
| Note that there is no support for any bit operations or something similar. |
| |
| * special note regarding `not`: The `is` and `in` operators support negation |
| using an infix notation too: ``foo is not bar`` and ``foo not in bar`` |
| instead of ``not foo is bar`` and ``not foo in bar``. All other expressions |
| require a prefix notation: ``not (foo and bar)``. |
| |
| |
| With Jinja 1.2 onwards it's possible to replace basic if/else blocks with the |
| inline `if` / `else` expression. The following two examples evaluate to the |
| same: |
| |
| .. sourcecode:: jinja |
| |
| {{ "something" if expr else "otherthing" }} |
| |
| {% if expr %}something{% else %}otherthing{% endif %} |
| |
| |
| Boolean Values |
| ============== |
| |
| In If-Conditions Jinja performs a boolean check. All empty values (eg: empty |
| lists ``[]``, empty dicts ``{}`` etc) evaluate to `false`. Numbers that are |
| equal to `0`/`0.00` are considered `false` too. The boolean value of other |
| objects depends on the behavior the application developer gave it. Usually |
| items are `true`. |
| |
| Here some examples that should explain it: |
| |
| .. sourcecode:: jinja |
| |
| {% if [] %} |
| will always be false because it's an empty list |
| |
| {% if {} %} |
| false too. |
| |
| {% if ['foo'] %} |
| this is true. Because the list is not empty. |
| |
| {% if "foobar" %} |
| this is also true because the string is not empty. |
| |
| Slicing |
| ======= |
| |
| Some objects support slicing operations. For example lists: |
| |
| .. sourcecode:: jinja |
| |
| {% for item in items[:5] %} |
| This will only iterate over the first 5 items of the list |
| |
| {% for item in items[5:10] %} |
| This will only iterate from item 5 to 10. |
| |
| {% for item in items[:10:2] %} |
| This will only yield items from start to ten and only returing |
| even items. |
| |
| For more informations about slicing have a look at the `slicing chapter`_ |
| in the "Dive into Python" e-book. |
| |
| Macros |
| ====== |
| |
| If you want to use a partial template in more than one place, you might want to |
| create a macro from it: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro show_user user %} |
| <h1>{{ user.name|e }}</h1> |
| <div class="text"> |
| {{ user.description }} |
| </div> |
| {% endmacro %} |
| |
| Now you can use it from everywhere in the code by passing it an item: |
| |
| .. sourcecode:: jinja |
| |
| {% for user in users %} |
| {{ show_user(user) }} |
| {% endfor %} |
| |
| You can also specify more than one value: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro show_dialog title, text %} |
| <div class="dialog"> |
| <h1>{{ title|e }}</h1> |
| <div class="text">{{ text|e }}</div> |
| </div> |
| {% endmacro %} |
| |
| {{ show_dialog('Warning', 'something went wrong i guess') }} |
| |
| *Improvements in Jinja 1.1*: |
| |
| Starting with Jinja 1.1 it's possible to use optional parentheses |
| around the macro arguments: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro foo(a, b) %} |
| ... |
| {% endmacro %} |
| |
| Additionally extra arguments passed to the macro end up in the |
| special variable `varargs`. So you can have a macro like this: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro make_list() %} |
| {% if varargs %} |
| <ul> |
| {% for item in varargs %} |
| <li>{{ item|e }}</li> |
| {% endfor %} |
| </ul> |
| {% endif %} |
| {% endmacro %} |
| |
| {{ make_list("John", "Jane", "Marcus", "Heinrich") }} |
| |
| If a macro parameter is called `varargs` the additional extra |
| arguments are not accessible. |
| |
| For information regarding the visibility of macros have a look at the |
| `Scopes and Variable Behavior`_ section. |
| |
| |
| Extended Macro Call |
| =================== |
| |
| *new in Jinja 1.1* |
| |
| Jinja 1.1 adds a new special tag that you can use to pass some evaluable |
| template code to a macro. Here an example macro that uses the features of |
| the ``{% call %}`` tag: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro dialog title %} |
| <div class="dialog"> |
| <h3>{{ title }}</h3> |
| <div class="text"> |
| {{ caller() }} |
| </div> |
| </div> |
| {% endmacro %} |
| |
| Called the normal way `caller` will be undefined, but if you call it |
| using the new `{% call %}` tag you can pass it some data: |
| |
| .. sourcecode:: html+jinja |
| |
| {% call dialog('Hello World') %} |
| This is an example dialog |
| {% endcall %} |
| |
| Now the data wrapped will be inserted where you put the `caller` call. |
| |
| If you pass `caller()` some keyword arguments those are added to the |
| namespace of the wrapped template data: |
| |
| .. sourcecode:: html+jinja |
| |
| {% macro makelist items %} |
| <ul> |
| {%- for item in items %} |
| <li>{{ caller(item=item) }}</li> |
| {%- endfor %} |
| </ul> |
| {%- endmacro %} |
| |
| {% call makelist([1, 2, 3, 4, 5, 6]) -%} |
| [[{{ item }}]] |
| {%- endcall %} |
| |
| This will then produce this output: |
| |
| .. sourcecode:: html |
| |
| <ul> |
| <li>[[1]]</li> |
| <li>[[2]]</li> |
| <li>[[3]]</li> |
| <li>[[4]]</li> |
| <li>[[5]]</li> |
| <li>[[6]]</li> |
| </ul> |
| |
| |
| Template Inclusion |
| ================== |
| |
| You can load another template at a given position using ``{% include %}``. |
| Usually it's a better idea to use inheritance but if you for example want to |
| load macros, `include` works better than `extends`: |
| |
| .. sourcecode:: jinja |
| |
| {% include "myhelpers.html" %} |
| {{ my_helper("foo") }} |
| |
| If you define a macro called ``my_helper`` in ``myhelpers.html``, you can now |
| use it from the template as shown above. |
| |
| Please keep in mind that include does not render the template indenpendently |
| but includes the processing instructions into the current template. Thus if the |
| included template contains a ``{% extends %}`` tag it also affects the current |
| template. |
| |
| This is intended because it makes it possible to include macros from other |
| templates. |
| |
| *new in Jinja 1.1* you can now render an included template to a string that is |
| evaluated in an indepdendent environment by calling `rendertemplate`. See the |
| documentation for this function in the `builtins`_ documentation. |
| |
| |
| Filtering Blocks |
| ================ |
| |
| Sometimes it could be a good idea to filter a complete block of text. For |
| example, if you want to escape some html code: |
| |
| .. sourcecode:: jinja |
| |
| {% filter escape %} |
| <html> |
| <code>goes here</code> |
| </html> |
| {% endfilter %} |
| |
| Of course you can chain filters too: |
| |
| .. sourcecode:: jinja |
| |
| {% filter lower|escape %} |
| <B>SOME TEXT</B> |
| {% endfilter %} |
| |
| returns ``"<b>some text</b>"``. |
| |
| |
| Defining Variables |
| ================== |
| |
| You can also define variables in the namespace using the ``{% set %}`` tag: |
| |
| .. sourcecode:: jinja |
| |
| {% set foo = 'foobar' %} |
| {{ foo }} |
| |
| This should ouput ``foobar``. |
| |
| For information regarding the visibility of variables have a look at the |
| `Scopes and Variable Behavior`_ section. |
| |
| |
| Reserved Keywords |
| ================= |
| |
| Jinja has some keywords you cannot use a variable names. This limitation |
| exists to make templates look coherent. Syntax highlighters won't mess things |
| up and you won't have the situation that some names work depending on the |
| context. |
| |
| The following keywords exist and cannot be used as identifiers: |
| |
| `and`, `block`, `cycle`, `elif`, `else`, `endblock`, `endfilter`, |
| `endfor`, `endif`, `endmacro`, `endraw`, `endtrans`, `extends`, `filter`, |
| `for`, `if`, `in`, `include`, `is`, `macro`, `not`, `or`, `pluralize`, |
| `print`, `raw`, `recursive`, `set`, `trans`, `call`, `endcall` |
| |
| If you want to use such a name you have to prefix or suffix it or use |
| alternative names: |
| |
| .. sourcecode:: jinja |
| |
| {% for macro_ in macros %} |
| {{ macro_('foo') }} |
| {% endfor %} |
| |
| |
| .. _slicing chapter: http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice |
| .. _Scopes and Variable Behavior: scopes.txt |
| .. _builtins: builtins.txt |