Django Template For Loop
The {% for %} tag iterates over a list, queryset, or dictionary in a template, with forloop giving you loop metadata like the current index.
The {% for %} Tag
{% for %} iterates over any list, tuple, queryset, or other iterable found in the context, running the enclosed block once per item and binding a loop variable of your choosing to the current item. Like if, it must be explicitly closed with {% endfor %}.
Example
<ul>
{% for article in articles %}
<li>{{ article.title }}</li>
{% endfor %}
</ul>Loop Metadata with forloop
Inside every for loop, Django provides a forloop variable with metadata about the current iteration: forloop.counter (1-indexed position), forloop.counter0 (0-indexed), forloop.first and forloop.last (booleans), forloop.revcounter (position counting down to 1), and forloop.parentloop (the enclosing loop's forloop, for nested loops).
Example
<table>
{% for article in articles %}
<tr class="{% if forloop.last %}last-row{% endif %}">
<td>{{ forloop.counter }}</td>
<td>{{ article.title }}</td>
</tr>
{% endfor %}
</table>Handling Empty Lists and Nested Loops
The optional {% empty %} clause renders in place of the loop body when the iterable has zero items, saving you a separate {% if articles %} check. Inside a nested loop, forloop.parentloop gives you access to the outer loop's counter, since the inner forloop only tracks the inner iteration.
Example
{% for category in categories %}
<h2>{{ category.name }}</h2>
<ol>
{% for product in category.products.all %}
<li>{{ forloop.parentloop.counter }}.{{ forloop.counter }} {{ product.name }}</li>
{% empty %}
<li>No products in this category yet.</li>
{% endfor %}
</ol>
{% empty %}
<p>No categories to show.</p>
{% endfor %}- forloop.counter — current iteration, starting at 1
- forloop.counter0 — current iteration, starting at 0
- forloop.first / forloop.last — True on the first or last iteration
- forloop.revcounter — iterations remaining, counting down to 1
- forloop.parentloop — the enclosing loop's forloop, for nested loops
Exercise: Django Template For Loop
Which tag correctly ends a for loop in a Django template?