Tags¶
Tags control template logic and structure. They use {% %} syntax.
All tag arguments support filter expressions and filter chaining. For example:
{% set x = " hello "|trim|upper %}
{% with greeting="hello"|upper %}
{% for i in "5,1,2"|split:","|sort %}
{% cycle "a"|upper "b"|upper %}
{% firstof "" "world"|upper %}
{% ifchanged "hello"|upper %}
Table of Contents¶
Control Flow¶
if / elif / else / endif¶
Conditional rendering with a wide range of operators.
Supported operators: ==, !=, <, <=, >, >=, in, not in, and, or, not
Operator precedence (highest to lowest): comparison → and → or
for / empty / endfor¶
Loop over arrays and objects. Injects forloop meta tracking.
forloop Metadata¶
| Variable | Description |
|----------|-------------|
| forloop.counter | 1-based index |
| forloop.counter0 | 0-based index |
| forloop.revcounter | Reverse 1-based index |
| forloop.revcounter0 | Reverse 0-based index |
| forloop.first | true on first iteration |
| forloop.last | true on last iteration |
| forloop.parentloop | Parent loop context (nested loops) |
Real-world table with alternating row classes:
<table>
{% for row in rows %}
<tr class="{% cycle 'row-odd' 'row-even' %}">
<td>{{ row.name }}</td>
<td>{{ row.value }}</td>
</tr>
{% endfor %}
</table>
with / endwith¶
Scope localized variables.
cycle¶
Cycle through values sequentially.
firstof¶
Return the first truthy value.
Variable Assignment¶
set¶
Assign a value to a variable.
Variables set with {% set %} persist in the current scope and can be used after the tag.
Change Detection¶
ifchanged / endifchanged¶
Render the body only when a value changes.
Date and Time¶
now¶
Output the current date/time.
Uses the same format codes as the date filter (Django-style tokens like Y, m, d, H, i, s, F).
Real-world copyright footer:
Utility Tags¶
static¶
Generate a static file URL.
<link rel="stylesheet" href="{% static "css/main.css" %}">
<script src="{% static "js/app.js" %}"></script>
<img src="{% static "images/logo.svg" }}" alt="{{ site.name }}">
Configure the prefix at compile time:
url¶
Build a URL from a route name.
Configure with a custom resolver:
regroup¶
Group a list by a common attribute.
{% regroup people by gender as departments %}
{% for dept in departments %}
<h3>{{ dept.grouper }}</h3>
{% for person in dept.list %}
<p>{{ person.name }}</p>
{% endfor %}
{% endfor %}
You can also use regroup as a filter inside a {% for %} loop:
{% for group in items|regroup:"category" %}
<h3>{{ group.grouper }}</h3>
{% for item in group.list %}
<p>{{ item.name }}</p>
{% endfor %}
{% endfor %}
spaceless¶
Remove whitespace between HTML tags.
Output: <div><span> hello </span></div>
widthratio¶
Calculate ratios for progress bars or scaling.
<!-- Calculate 25 out of 100 scaled to max-width 150 -->
{% widthratio score 100 150 %}
<!-- → 37 (floor of 25/100*150) -->
<!-- Progress bar width -->
<div class="bar" style="width: {% widthratio value max_value 100 %}px;"></div>
debug¶
Dump the current template context for debugging.
Outputs a <pre> block with all context variables.
Security Tags¶
csrf_token¶
Output a hidden CSRF token input.
The token value is HTML-escaped to prevent attribute injection. Requires csrf_token to be present in the template context.
csp_nonce_attr¶
Output a nonce attribute when csp_nonce is in the context.
If csp_nonce is present in context, the output is:
If csp_nonce is not present, the tag outputs nothing.
Comments and Raw Output¶
comment / endcomment¶
Block comments ignored during parsing.
verbatim / endverbatim¶
Treat content as raw text — template syntax is not parsed.
{% verbatim %}
This will NOT be parsed: {{ user.name }}
And this won't either: {% if x %}
{% endverbatim %}
You can also name a verbatim block:
Autoescape¶
Control HTML escaping for a block.
{% autoescape on %}
{{ user_input }} {# escaped → <script>... #}
{% endautoescape %}
{% autoescape off %}
{{ trusted_html }} {# not escaped → raw HTML #}
{% endautoescape %}
Library Loading¶
load¶
Activate a template library. Built-in libraries (humanize, cache, lorem) are auto-activated — you only need {% load %} for custom libraries you've registered.
Then use in templates:
Built-in libraries:
-
i18n—{% trans %},{% blocktrans %},{% language %} -
humanize—intcomma,intword,apnumber,ordinal,naturalday -
cache—{% cache timeout key %}...{% endcache %} -
lorem—{% lorem %}tag andloremfilter
Template Tags¶
templatetag¶
Output literal template tag tokens. Useful when generating documentation or when the template syntax conflicts with another templating layer.
{% templatetag openblock %} if user.is_admin {% templatetag closeblock %}
<!-- Renders: {% if user.is_admin %} -->
{% templatetag openvariable %} name {% templatetag closevariable %}
<!-- Renders: {{ name }} -->
Available tokens:
| Token | Output |
|-------|--------|
| openblock | {% |
| closeblock | %} |
| openvariable | {{ |
| closevariable | }} |
| openbrace | { |
| closebrace | } |
| opencomment | {# |
| closecomment | #} |
Inheritance Tags¶
extends¶
Inherit from a parent template.
Can use expressions for dynamic parent selection:
Security: Path traversal is blocked — {% extends "../../etc/passwd" %} is rejected.
block / endblock¶
Define a block that can be overridden by child templates.
<!-- child.html -->
{% extends "base.html" %}
{% block content %}
<h1>Child content</h1>
{{ block.super }}
{% endblock %}
block.super¶
A special variable (not a tag). When used inside a {% block %}, it renders the parent template's version of that block.
See Template Inheritance for a detailed guide.
include¶
Include another template's content inline.
{% include "header.html" %}
{% include "header.html" with title="Hello" %}
{% include "header.html#partial_name" %}
{% include "header.html" with title="Hello" %}
Security: Path traversal is blocked.
Partial Tags¶
partialdef / endpartialdef¶
Define a reusable partial block.
{% partialdef card %}
<div class="card">
<h3>{{ title|default:"Untitled" }}</h3>
<p>{{ body|truncatewords:30 }}</p>
{% if featured %}<em>Featured</em>{% endif %}
</div>
{% endpartialdef %}
Options:
| Option | Description |
|--------|-------------|
| inline | Renders the definition inline at its location during parse (the body appears in output AND registers for later use). |
{% partialdef greeting inline %}
Hello {{ name }}!
{% endpartialdef %}
<!-- Above line ALSO outputs "Hello World!" when rendered -->
Programmatic access:
partial¶
Render a named partial.
{% partial card %}
{% partial card with title="Custom" body="World" %}
{% partial greeting with name=user.name %}
See Partial Templates for a detailed guide.
i18n Tags¶
trans¶
Translate a string.
{% trans "Hello, world!" %}
{% trans "Hello, %s!" name=user.name %}
{% trans context "verb" "He runs" %}
blocktrans / endblocktrans¶
Translate a block of text with variable interpolation and pluralization.
{% blocktrans with name=user.name %}
Hello, {{ name }}!
{% endblocktrans %}
{% blocktrans count items|length %}
{{ count }} item
{% plural %}
{{ count }} items
{% endblocktrans %}
language / endlanguage¶
Switch language temporarily for a block.
Filter and Utility Tags¶
filter / endfilter¶
Apply a filter to a block of content.
verbatim / endverbatim¶
Render the body as raw text, ignoring template syntax inside.
resetcycle¶
Reset the cycle counter back to the beginning.
{% cycle "a" "b" "c" as marker silent %}
{{ marker }}
{% resetcycle %}
{% cycle "a" "b" "c" as marker silent %}
{{ marker }}
endfirstof¶
Closes a {% firstof %} block explicitly. It is a no-op and emits nothing.
translate¶
Alias for {% trans %}. Works identically.
blocktranslate / endblocktranslate¶
Alias for {% blocktrans %}. Works identically.