those.
You can use a dot (``.``) to access attributes of a variable, alternative the
-so-called "subscribe" syntax (``[]``) can be used. The following lines do
+so-called "subscript" syntax (``[]``) can be used. The following lines do
the same::
{{ foo.bar }}
configuration, the default behavior is that it evaluates to an empty string
if printed and that you can iterate over it, but every other operation fails.
+.. _notes-on-subscriptions:
+
+.. admonition:: Implementation
+
+ For convenience sake ``foo.bar`` in Jinja2 does the following things on
+ the Python layer:
+
+ - check if there is an attribute called `bar` on `foo`.
+ - if there is not, check if there is an item ``'bar'`` in `foo`.
+ - if there is not, return an undefined object.
+
+ ``foo['bar']`` on the other hand works mostly the same with the a small
+ difference in the order:
+
+ - check if there is an item ``'bar'`` in `foo`.
+ - if there is not, check if there is an attribute called `bar` on `foo`.
+ - if there is not, return an undefined object.
+
+ This is important if an object has an item or attribute with the same
+ name. Additionally there is the :func:`attr` filter that just looks up
+ attributes.
+
.. _filters:
Filters
This will yield all elements without whitespace between them. If `seq` was
a list of numbers from ``1`` to ``9`` the output would be ``123456789``.
-Note that you must not use a whitespace between the tag and the minus sign:
+If :ref:`line-statements` are enabled they strip leading whitespace
+automatically up to the beginning of the line.
+
+.. admonition:: Note
+
+ You must not use a whitespace between the tag and the minus sign.
+
+ **valid**::
- valid:
{%- if foo -%}...{% endif %}
- invalid:
+ **invalid**::
{% - if foo - %}...{% endif %}
-If :ref:`line-statements` are enabled they strip leading whitespace
-automatically up to the beginning of the line.
-
Escaping
--------
# endfor
+.. admonition:: Note
+
+ Line statements can span multiple lines if there are open parentheses,
+ braces or brackets::
+
+ <ul>
+ # for href, caption in [('index.html', 'Index'),
+ ('about.html', 'About')]:
+ <li><a href="{{ href }}">{{ caption }}</a></li>
+ # endfor
+ </ul>
+
+
.. _template-inheritance:
Template Inheritance
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
-
Unlike Python Jinja does not support multiple inheritance. So you can only have
one extends tag called per rendering.
{% endblock %}
+Named Block End-Tags
+~~~~~~~~~~~~~~~~~~~~
+
+Jinja2 allows you to put the name of the block after the end tag for better
+readability::
+
+ {% block sidebar %}
+ {% block inner_sidebar %}
+ ...
+ {% endblock inner_sidebar %}
+ {% endblock sidebar %}
+
+However the name after the `endblock` word must match the block name.
+
+
HTML Escaping
-------------
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
+With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound
+cycling. For more information have a look at the :ref:`builtin-globals`.
+
.. _loop-filtering:
Unlike in Python it's not possible to `break` or `continue` in a loop. You
This is `true` if the macro accesses the special `caller` variable and may
be called from a :ref:`call<call>` tag.
+If a macro name starts with an underscore it's not exported and can't
+be imported.
+
.. _call:
{% endcall %}
It's also possible to pass arguments back to the call block. This makes it
-useful as replacement for loops. It is however not possible to call a
-call block with another call block.
+useful as replacement for loops. Generally speaking a call block works
+exactly like an macro, just that it doesn't have a name.
Here an example of how a call block can be used with arguments::
{% endcall %}
+Filters
+~~~~~~~
+
+Filter sections allow you to apply regular Jinja2 filters on a block of
+template data. Just wrap the code in the special `filter` section::
+
+ {% filter upper %}
+ This text becomes uppercase
+ {% endfilter %}
+
+
Assignments
~~~~~~~~~~~
</dl>
<p>{{ textarea('comment') }}</p>
+Macros and variables starting with one ore more underscores are private and
+cannot be imported.
+
.. _import-visibility:
{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}
+.. admonition:: Note
+
+ In Jinja 2.0 the context that was passed to the included template
+ did not include variables define in the template. As a matter of
+ fact this did not work::
+
+ {% for box in boxes %}
+ {% include "render_box.html" %}
+ {% endfor %}
+
+ The included template ``render_box.html`` is not able to access
+ `box` in Jinja 2.0, but in Jinja 2.1.
+
.. _expressions:
filter.
true / false:
- true is always true and false is always false. Keep in mind that those
- literals are lowercase!
+ true is always true and false is always false.
+
+.. admonition:: Note
+
+ The special constants `true`, `false` and `none` are indeed lowercase.
+ Because that caused confusion in the past, when writing `True` expands
+ to an undefined variable that is considered false, all three of them can
+ be written in title case too (`True`, `False`, and `None`). However for
+ consistency (all Jinja identifiers are lowercase) you should use the
+ lowercase versions.
Math
~~~~
(expr)
group an expression.
-Note that there is no support for any bit operations or something similar.
+.. admonition:: Note
-- 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).``
+ 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).``
Other Operators
The general syntax is ``<do something> if <something is true> else <do
something else>``.
+The `else` part is optional. If not provided the else block implicitly
+evaluates into an undefined object::
+
+ {{ '[%s]' % page.title if page.title }}
+
.. _builtin-filters:
.. jinjatests::
+.. _builtin-globals:
List of Global Functions
------------------------
A convenient alternative to dict literals. ``{'foo': 'bar'}`` is the same
as ``dict(foo='bar')``.
+.. class:: cycler(\*items)
+
+ The cycler allows you to cycle among values similar to how `loop.cycle`
+ works. Unlike `loop.cycle` however you can use this cycler outside of
+ loops or over multiple loops.
+
+ This is for example very useful if you want to show a list of folders and
+ files, with the folders on top, but both in the same list with alteranting
+ row colors.
+
+ The following example shows how `cycler` can be used::
+
+ {% set row_class = cycler('odd', 'even') %}
+ <ul class="browser">
+ {% for folder in folders %}
+ <li class="folder {{ row_class.next() }}">{{ folder|e }}</li>
+ {% endfor %}
+ {% for filename in files %}
+ <li class="file {{ row_class.next() }}">{{ filename|e }}</li>
+ {% endfor %}
+ </ul>
+
+ A cycler has the following attributes and methods:
+
+ .. method:: reset()
+
+ Resets the cycle to the first item.
+
+ .. method:: next()
+
+ Goes one item a head and returns the then current item.
+
+ .. attribute:: current
+
+ Returns the current item.
+
+ **new in Jinja 2.1**
+
Extensions
----------
For multiple placeholders always use keyword arguments to `format` as other
languages may not use the words in the same order.
+
+
+Expression Statement
+~~~~~~~~~~~~~~~~~~~~
+
+If the expression-statement extension is loaded a tag called `do` is available
+that works exactly like the regular variable expression (``{{ ... }}``) just
+that it doesn't print anything. This can be used to modify lists::
+
+ {% do navigation.append('a string') %}
+
+
+Loop Controls
+~~~~~~~~~~~~~
+
+If the application enables the :ref:`loopcontrols-extension` it's possible to
+use `break` and `continue` in loops. When `break` is reached, the loop is
+terminated, if `continue` is eached the processing is stopped and continues
+with the next iteration.
+
+Here a loop that skips every second item::
+
+ {% for user in users %}
+ {%- if loop.index is even %}{% continue %}{% endif %}
+ ...
+ {% endfor %}
+
+Likewise a look that stops processing after the 10th iteration::
+
+ {% for user in users %}
+ {%- if loop.index >= 10 %}{% break %}{% endif %}
+ {%- endfor %}