Jinja Control Structure: Recursive Loops
n
nn
n
How It Works
nTo make a loop recursive, you must add the `recursive` modifier to the `for` loop’s definition. The special `loop` variable then becomes a callable function that you can pass a new iterable to. This new iterable should contain the child items that you want to process in the next level of recursion. The loop variable will always refer to the closest (innermost) loop.nnIf you have multiple levels of nested loops and need to reference an outer loop, you can rebind the `loop` variable to a different name, for example: `{% set outer_loop = loop %}`. This allows you to call the outer loop recursively from within an inner loop. This is a common pattern for managing complex recursive logic.n
Syntax
n
{% for item in iterable recursive %}n <!-- Code for the current item -->n {% if item.children %}n <!-- Calling loop(item.children) starts the recursion -->n {{ loop(item.children) }}n {% endif %}n{% endfor %}
nn
nn
n
Demonstration with Code Samples
nThis example demonstrates how to implement a sitemap with a recursive loop. The `sitemap` data structure is a nested list of dictionaries, where each dictionary can have a `children` key that contains a sub-list of more items.n
1. Jinja2 Template for a Sitemap
nThe `for` loop is declared with the `recursive` keyword, and within the loop, the `loop(item.children)` call is used to recurse into the next level of the sitemap.n
{% set sitemap = [n { 'href': '/', 'title': 'Home' },n { 'href': '/products', 'title': 'Products', 'children': [n { 'href': '/products/electronics', 'title': 'Electronics' },n { 'href': '/products/apparel', 'title': 'Apparel' }n ] },n { 'href': '/about', 'title': 'About' }n] %}nn<ul class="sitemap">n{%- for item in sitemap recursive %}n <li><a href="{{ item.href|e }}">{{ item.title }}</a>n {%- if item.children -%}n <ul class="submenu">{{ loop(item.children) }}</ul>n {%- endif %}</li>n{%- endfor %}n</ul>
nExplanation: In the first iteration, the loop processes the top-level items. When it encounters the “Products” item, which has a `children` list, the `if` condition is met. The `loop(item.children)` call is then executed, which starts a new loop for the child items. This process continues for any nested `children` lists, dynamically generating the nested HTML structure.nn
n
