Loops
Jinja's for
loops enable you to iterate over data structures such as lists, dictionaries, and tuples, to produce dynamic content. For instance, you can use a loop to generate a list of blog posts on a website or display the names of all team members on a company page.
Here is an example of Jinja loop that iterates over a list of customers named customers
:
{% for customer in customers %}
{{ customer.name }}
{% endfor %}
As with conditionals, you need to explicitly mark the end of the loop block, in this case using endfor
.
Loop over dictionaries
If you are iterating over a dictionary, you need to use a slightly different syntax
{% for key, value in my_dict.items() %}
{{ key }} = {{ value }}
{% endfor %}
Use an else statement
You can optionally also add an else
statement to the loop: that statement will be used if the data structure you are iterating over is empty. For example:
{% for customer in customers %}
{{ customer.name }}
{% else %}
No customer.
{% endfor %}
Use loop-specific variables
Jinja provides several loop-specific variables that are available within your loop block: an example is loop.first
, which is True
if your loop is iterating over its first element and False
in every other case. Here is a practical example:
# file: jinja-templates/03-loops.txt
{%- for customer in customers -%}
{% if not loop.first %},{% endif %}{{ customer.name -}}
{% endfor %}
This template will print all customer names in a single line, prepending each of them with a comma with the exception of the first one.
Rendering the template with the following input
>>> tpl = env.get_template("03-loops.txt")
>>> tpl.render(customers=[{"name": "A"}, {"name": "B"}, {"name": "C"}])
produces
A,B,C
A
does not have a leading comma because not loop.first
returned False
, since A
is the first element in the list.
Avoiding unwanted commas is especially useful when using loops to build an SQL query with a dynamic list of columns. For example, the following template generates a valid SQL query, without extra trailing commas:
{% set values = [ 'Central','South','East','West'] %}
SELECT
{% for value in values %}
'{{value}}' as {{ value }}
{% if not loop.last %},{% endif %}
{% endfor %}
Here is an overview of the loop-specific variables, while the complete list is available here:
Variable | Description |
---|---|
loop.index | The current iteration of the loop. (1 indexed) |
loop.revindex | The number of iterations from the end of the loop (1 indexed) |
loop.first | True if first iteration. |
loop.last | True if last iteration. |
loop.length | The number of items in the sequence. |
loop.cycle | Cycle through a given list of strings or variables. E.g.: {{ loop.cycle('odd', 'even') }} |
loop.previtem | The item from the previous iteration of the loop. Undefined during the first iteration. |
loop.nextitem | The 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). |
Filter elements
You can use an if
statement to filter the sequence during iteration, allowing you to skip those elements (if any) that do not meet the condition.
For example:
{% for customer in customers if customer.is_business %}
{{ customer.name }}
{% else %}
No customer.
{% endfor %}
will only return the names of those customers for which is_business == True
.
Just like with regular conditional statements, you can combine multiple conditions using logical operators.