List of Control Structures

A control structure refers to all those things that control the flow of aprogram - conditionals (i.e. if/elif/else), for-loops, as well as things likemacros and blocks. With the default syntax, control structures appear inside{% … %} blocks.

For

Loop over each item in a sequence. For example, to display a list of usersprovided in a variable called users:

  1. <h1>Members</h1>
  2. <ul>
  3. {% for user in users %}
  4. <li>{{ user.username|e }}</li>
  5. {% endfor %}
  6. </ul>

As variables in templates retain their object properties, it is possible toiterate over containers like dict:

  1. <dl>
  2. {% for key, value in my_dict.items() %}
  3. <dt>{{ key|e }}</dt>
  4. <dd>{{ value|e }}</dd>
  5. {% endfor %}
  6. </dl>

Note, however, that Python dicts are not ordered; so you might want toeither pass a sorted list of tuple s – or acollections.OrderedDict – to the template, or use the dictsort filter.

Inside of a for-loop block, you can access some special variables:

VariableDescription
loop.indexThe current iteration of the loop. (1 indexed)
loop.index0The current iteration of the loop. (0 indexed)
loop.revindexThe number of iterations from the end of the loop(1 indexed)
loop.revindex0The number of iterations from the end of the loop(0 indexed)
loop.firstTrue if first iteration.
loop.lastTrue if last iteration.
loop.lengthThe number of items in the sequence.
loop.cycleA helper function to cycle between a list ofsequences. See the explanation below.
loop.depthIndicates how deep in a recursive loopthe rendering currently is. Starts at level 1
loop.depth0Indicates how deep in a recursive loopthe rendering currently is. Starts at level 0
loop.previtemThe item from the previous iteration of the loop.Undefined during the first iteration.
loop.nextitemThe item from the following iteration of the loop.Undefined during the last iteration.
loop.changed(*val)True if previously called with a different value(or not called at all).

Within a for-loop, it’s possible to cycle among a list of strings/variableseach time through the loop by using the special loop.cycle helper:

  1. {% for row in rows %}
  2. <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
  3. {% endfor %}

Since Jinja 2.1, an extra cycle helper exists that allows loop-unboundcycling. For more information, have a look at the List of Global Functions.

Unlike in Python, it’s not possible to break or continue in a loop. Youcan, however, filter the sequence during iteration, which allows you to skipitems. The following example skips all the users which are hidden:

  1. {% for user in users if not user.hidden %}
  2. <li>{{ user.username|e }}</li>
  3. {% endfor %}

The advantage is that the special loop variable will count correctly; thusnot counting the users not iterated over.

If no iteration took place because the sequence was empty or the filteringremoved all the items from the sequence, you can render a default blockby using else:

  1. <ul>
  2. {% for user in users %}
  3. <li>{{ user.username|e }}</li>
  4. {% else %}
  5. <li><em>no users found</em></li>
  6. {% endfor %}
  7. </ul>

Note that, in Python, else blocks are executed whenever the correspondingloop did notbreak. Since Jinja loops cannot break anyway,a slightly different behavior of the else keyword was chosen.

It is also possible to use loops recursively. This is useful if you aredealing with recursive data such as sitemaps or RDFa.To use loops recursively, you basically have to add the recursive modifierto the loop definition and call the loop variable with the new iterablewhere you want to recurse.

The following example implements a sitemap with recursive loops:

  1. <ul class="sitemap">
  2. {%- for item in sitemap recursive %}
  3. <li><a href="{{ item.href|e }}">{{ item.title }}</a>
  4. {%- if item.children -%}
  5. <ul class="submenu">{{ loop(item.children) }}</ul>
  6. {%- endif %}</li>
  7. {%- endfor %}
  8. </ul>

The loop variable always refers to the closest (innermost) loop. If wehave more than one level of loops, we can rebind the variable loop bywriting {% set outer_loop = loop %} after the loop that we want touse recursively. Then, we can call it using {{ outer_loop(…) }}

Please note that assignments in loops will be cleared at the end of theiteration and cannot outlive the loop scope. Older versions of Jinja2 hada bug where in some circumstances it appeared that assignments would work.This is not supported. See Assignments for more information abouthow to deal with this.

If all you want to do is check whether some value has changed since thelast iteration or will change in the next iteration, you can use previtem_and _nextitem:

  1. {% for value in values %}
  2. {% if loop.previtem is defined and value > loop.previtem %}
  3. The value just increased!
  4. {% endif %}
  5. {{ value }}
  6. {% if loop.nextitem is defined and loop.nextitem > value %}
  7. The value will increase even more!
  8. {% endif %}
  9. {% endfor %}

If you only care whether the value changed at all, using changed is eveneasier:

  1. {% for entry in entries %}
  2. {% if loop.changed(entry.category) %}
  3. <h2>{{ entry.category }}</h2>
  4. {% endif %}
  5. <p>{{ entry.message }}</p>
  6. {% endfor %}

If

The if statement in Jinja is comparable with the Python if statement.In the simplest form, you can use it to test if a variable is defined, notempty and not false:

  1. {% if users %}
  2. <ul>
  3. {% for user in users %}
  4. <li>{{ user.username|e }}</li>
  5. {% endfor %}
  6. </ul>
  7. {% endif %}

For multiple branches, elif and else can be used like in Python. You canuse more complex Expressions there, too:

  1. {% if kenny.sick %}
  2. Kenny is sick.
  3. {% elif kenny.dead %}
  4. You killed Kenny! You bastard!!!
  5. {% else %}
  6. Kenny looks okay --- so far
  7. {% endif %}

If can also be used as an inline expression and forloop filtering.

Macros

Macros are comparable with functions in regular programming languages. Theyare useful to put often used idioms into reusable functions to not repeatyourself (“DRY”).

Here’s a small example of a macro that renders a form element:

  1. {% macro input(name, value='', type='text', size=20) -%}
  2. <input type="{{ type }}" name="{{ name }}" value="{{
  3. value|e }}" size="{{ size }}">
  4. {%- endmacro %}

The macro can then be called like a function in the namespace:

  1. <p>{{ input('username') }}</p>
  2. <p>{{ input('password', type='password') }}</p>

If the macro was defined in a different template, you have toimport it first.

Inside macros, you have access to three special variables:

  • varargs
  • If more positional arguments are passed to the macro than accepted by themacro, they end up in the special varargs variable as a list of values.

  • kwargs

  • Like varargs but for keyword arguments. All unconsumed keywordarguments are stored in this special variable.

  • caller

  • If the macro was called from a call tag, the caller is storedin this variable as a callable macro.

Macros also expose some of their internal details. The following attributesare available on a macro object:

  • name
  • The name of the macro. {{ input.name }} will print input.

  • arguments

  • A tuple of the names of arguments the macro accepts.

  • defaults

  • A tuple of default values.

  • catch_kwargs

  • This is true if the macro accepts extra keyword arguments (i.e.: accessesthe special kwargs variable).

  • catch_varargs

  • This is true if the macro accepts extra positional arguments (i.e.:accesses the special varargs variable).

  • caller

  • This is true if the macro accesses the special caller variable and maybe called from a call tag.

If a macro name starts with an underscore, it’s not exported and can’tbe imported.

Call

In some cases it can be useful to pass a macro to another macro. For thispurpose, you can use the special call block. The following example showsa macro that takes advantage of the call functionality and how it can beused:

  1. {% macro render_dialog(title, class='dialog') -%}
  2. <div class="{{ class }}">
  3. <h2>{{ title }}</h2>
  4. <div class="contents">
  5. {{ caller() }}
  6. </div>
  7. </div>
  8. {%- endmacro %}
  9. {% call render_dialog('Hello World') %}
  10. This is a simple dialog rendered by using a macro and
  11. a call block.
  12. {% endcall %}

It’s also possible to pass arguments back to the call block. This makes ituseful as a replacement for loops. Generally speaking, a call block worksexactly like a macro without a name.

Here’s an example of how a call block can be used with arguments:

  1. {% macro dump_users(users) -%}
  2. <ul>
  3. {%- for user in users %}
  4. <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
  5. {%- endfor %}
  6. </ul>
  7. {%- endmacro %}
  8. {% call(user) dump_users(list_of_user) %}
  9. <dl>
  10. <dl>Realname</dl>
  11. <dd>{{ user.realname|e }}</dd>
  12. <dl>Description</dl>
  13. <dd>{{ user.description }}</dd>
  14. </dl>
  15. {% endcall %}

Filters

Filter sections allow you to apply regular Jinja2 filters on a block oftemplate data. Just wrap the code in the special filter section:

  1. {% filter upper %}
  2. This text becomes uppercase
  3. {% endfilter %}

Assignments

Inside code blocks, you can also assign values to variables. Assignments attop level (outside of blocks, macros or loops) are exported from the templatelike top level macros and can be imported by other templates.

Assignments use the set tag and can have multiple targets:

  1. {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
  2. {% set key, value = call_something() %}

Scoping Behavior

Please keep in mind that it is not possible to set variables inside ablock and have them show up outside of it. This also applies toloops. The only exception to that rule are if statements which do notintroduce a scope. As a result the following template is not goingto do what you might expect:

  1. {% set iterated = false %}
  2. {% for item in seq %}
  3. {{ item }}
  4. {% set iterated = true %}
  5. {% endfor %}
  6. {% if not iterated %} did not iterate {% endif %}

It is not possible with Jinja syntax to do this. Instead usealternative constructs like the loop else block or the special _loop_variable:

  1. {% for item in seq %}
  2. {{ item }}
  3. {% else %}
  4. did not iterate
  5. {% endfor %}

As of version 2.10 more complex use cases can be handled using namespaceobjects which allow propagating of changes across scopes:

  1. {% set ns = namespace(found=false) %}
  2. {% for item in items %}
  3. {% if item.check_something() %}
  4. {% set ns.found = true %}
  5. {% endif %}
  6. * {{ item.title }}
  7. {% endfor %}
  8. Found item having something: {{ ns.found }}

Note hat the obj.attr notation in the set tag is only allowed fornamespace objects; attempting to assign an attribute on any other objectwill raise an exception.

New in version 2.10: Added support for namespace objects

Block Assignments

Changelog

New in version 2.8.

Starting with Jinja 2.8, it’s possible to also use block assignments tocapture the contents of a block into a variable name. This can be usefulin some situations as an alternative for macros. In that case, instead ofusing an equals sign and a value, you just write the variable name and theneverything until {% endset %} is captured.

Example:

  1. {% set navigation %}
  2. <li><a href="/">Index</a>
  3. <li><a href="/downloads">Downloads</a>
  4. {% endset %}

The navigation variable then contains the navigation HTML source.

Changed in version 2.10.

Starting with Jinja 2.10, the block assignment supports filters.

Example:

  1. {% set reply | wordwrap %}
  2. You wrote:
  3. {{ message }}
  4. {% endset %}

Extends

The extends tag can be used to extend one template from another. You canhave multiple extends tags in a file, but only one of them may be executed ata time.

See the section about Template Inheritance above.

Blocks

Blocks are used for inheritance and act as both placeholders and replacementsat the same time. They are documented in detail in theTemplate Inheritance section.

Include

The include statement is useful to include a template and return therendered contents of that file into the current namespace:

  1. {% include 'header.html' %}
  2. Body
  3. {% include 'footer.html' %}

Included templates have access to the variables of the active context bydefault. For more details about context behavior of imports and includes,see Import Context Behavior.

From Jinja 2.2 onwards, you can mark an include with ignore missing; inwhich case Jinja will ignore the statement if the template to be includeddoes not exist. When combined with with or without context, it mustbe placed before the context visibility statement. Here are some validexamples:

  1. {% include "sidebar.html" ignore missing %}
  2. {% include "sidebar.html" ignore missing with context %}
  3. {% include "sidebar.html" ignore missing without context %}

Changelog

New in version 2.2.

You can also provide a list of templates that are checked for existencebefore inclusion. The first template that exists will be included. Ifignore missing is given, it will fall back to rendering nothing ifnone of the templates exist, otherwise it will raise an exception.

Example:

  1. {% include ['page_detailed.html', 'page.html'] %}
  2. {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}

Changelog

Changed in version 2.4: If a template object was passed to the template context, you caninclude that object using include.

Import

Jinja2 supports putting often used code into macros. These macros can go intodifferent templates and get imported from there. This works similarly to theimport statements in Python. It’s important to know that imports are cachedand imported templates don’t have access to the current template variables,just the globals by default. For more details about context behavior ofimports and includes, see Import Context Behavior.

There are two ways to import templates. You can import a complete templateinto a variable or request specific macros / exported variables from it.

Imagine we have a helper module that renders forms (called forms.html):

  1. {% macro input(name, value='', type='text') -%}
  2. <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
  3. {%- endmacro %}
  4. {%- macro textarea(name, value='', rows=10, cols=40) -%}
  5. <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
  6. }}">{{ value|e }}</textarea>
  7. {%- endmacro %}

The easiest and most flexible way to access a template’s variablesand macros is to import the whole template module into a variable.That way, you can access the attributes:

  1. {% import 'forms.html' as forms %}
  2. <dl>
  3. <dt>Username</dt>
  4. <dd>{{ forms.input('username') }}</dd>
  5. <dt>Password</dt>
  6. <dd>{{ forms.input('password', type='password') }}</dd>
  7. </dl>
  8. <p>{{ forms.textarea('comment') }}</p>

Alternatively, you can import specific names from a template into the currentnamespace:

  1. {% from 'forms.html' import input as input_field, textarea %}
  2. <dl>
  3. <dt>Username</dt>
  4. <dd>{{ input_field('username') }}</dd>
  5. <dt>Password</dt>
  6. <dd>{{ input_field('password', type='password') }}</dd>
  7. </dl>
  8. <p>{{ textarea('comment') }}</p>

Macros and variables starting with one or more underscores are private andcannot be imported.

Changelog

Changed in version 2.4: If a template object was passed to the template context, you canimport from that object.