Built-in Django tags
Django offers several built-in tags that offer immediate access to elaborate operations on Django templates. Unlike Django filters which operate on individual variables, tags are designed to produce results without a variable or operate across template sections.
I'll classify each of these built-in tags into functional sections so it's easier to identify them. The functional classes I'll use are: Dates, forms, comparison operations, loops, Python & filter operations, spacing and special characters, template structures, development and testing & urls.
Dates
{% now %}
.- The{% now %}
tag offers access to the current system time. The{% now %}
tag accepts a second argument to format the system date. For example, if the system date is 01/01/2022 for the statement{% now "F jS o" %}
the tag output is January 1st 2022. The string syntax for the{% now %}
tag is based on Django date characters described in table 3-3. It's also possible to use theas
keyword to re-use the value through a variable(e.g.{% now "Y" as current_year %}
and later in the template declareCopyright {{current_year}}
).
Tip The {% now %} tag can accept Django date variables: {% now "DATE_FORMAT" %}, {% now "DATETIME_FORMAT" %}, {% now "SHORT_DATE_FORMAT" %} or {% now "SHORT_DATETIME_FORMAT"}.The date variables in themselves are also composed of date strings. For example DATE_FORMAT default's to "N j, Y" (e.g. Jan 1, 2022), DATETIME_FORMAT defaults to "N j, Y, P" (e.g. Jan 1, 2022, 12 a.m.), SHORT_DATE_FORMAT defaults to "m/d/Y" (e.g. 01/01/2022) and SHORT_DATETIME_FORMAT defaults to "m/d/Y P" (e.g. 01/01/2022 12 a.m.). Each date variable can be overridden with different date strings in a project's settings.py file.
Forms
{% csrf_token %}
.- The{% csrf_token %}
tag provides a string to prevent cross site scripting. The{% csrf_token %}
tag is only intended to be used inside HTML<form>
tags. The data output of the{% csrf_token %}
tag allows Django to prevent request forgeries (e.g. HTTP POST requests) from form data submissions. More details about the{% csrf_token %}
tag are provided in the Django forms chapter.
Comparison operations
{% if %}
with{% elif %}
{% else %}
.- The{% if %}
tag is typically used in conjunction with the{% elif %}
and{% else %}
tags to evaluate more than one condition. An{% if %}
tag with an argument variable evaluates to true if a variable exists and is not empty or if the variable holds aTrue
boolean value. Listing 3-18 illustrates a series of{% if %}
tag examples.
Listing 3-18. Django {% if %} tag with {% elif %} and {% else %}
{% if drinks %} {% if drinks %} {% if drinks %} We have drinks! We have drinks We have drinks {% endif %} {% else %} {% elif drinks_on_sale %} No drinks,sorry We have drinks on sale! {% endif %} {% else %} No drinks, sorry {% endif %}
Note A variable must both exist and not be empty to evaluate to true. A variable that just exists and is empty evaluates to false.
{% if %}
withand
,or
andnot
operators.- The{% if %}
tag also supports theand
,or
andnot
operators to create more elaborate conditions. These operators allow you to compare if more than one variable is not empty (e.g.{% if drinks and drinks_on_sale %}
), if one or another variable is not empty (e.g.{% if drinks or drinks_on_sale %}
) or if a variable is empty (e.g.{% if not drinks %}
).{% if %}
with==
,!=
,<
,>
,<=
and>=
operators.- The{% if %}
tag also supports equal, not equal, larger than and less than operators to create conditions that compare variables to fixed strings or numbers. These operators allow you to compare if a variable equals a string or number (e.g.{% if drink == "mocha" %}
), if a variable does not equal a variable or number (e.g.{% if store.id != 2 %}
) or if a variable is greater than or lesser than a number (e.g.{% if store.id > 5 %}
).{% firstof %}
.- The{% firstof %}
tag is a shorthand tag to output the first variable in a set of variables that's not empty. The same functionality of the{% firstof %}
tag is achieved by nesting{% if %}
tags. Listing 3-19 illustrates a sample of the {% firstof %}
tag, as well as an equivalent set of nested{% if %}
tags.
Listing 3-19. Django {% firstof %} tag and equivalent {% if %}{% elif %}{% else %} tags
# Firstof example {% firstof var1 var2 var3 %} # Equivalent of firstof example {% if var1 %} {{var1|safe}} {% elif var2 %} {{var2|safe}} {% elif var3 %} {{var3|safe}} {% endif %} # Firstof example with a default value in case of no match (i.e, all variables are empty) {% firstof var1 var2 var3 "All vars are empty" %} # Assign the firstof result to another variable {% firstof var1 var2 var3 as resultof %} # resultof now contains result of firstof statement
{% if <value> in %}
and{% if <value> not in %}
.- The{% if %}
tag also supports thein
andnot in
operators to verify the presence of a constant or variable. For example{% if "mocha" in drinks %}
tests if the value"mocha"
is in thedrinks
list variable or{% if 2 not in stores %}
tests if the value2
is not in thestores
list variable. Although thein
andnot in
operators are commonly used to test list variables, it's also possible to test the presence of characters on strings (e.g.{% if "m" in drink %}
). In addition, it's also possible to compare if the value of one variable is present in another variable (e.g.{% if order_drink in drinks %}
).{% if <value> is <value> %}
and{% if <value> is not %}
.- The{% if %}
tag also supports theis
andis not
operators to make object-level comparisons. For example{% if target_drink is None %}
tests if the valuetarget_drink
is aNone
object or{% if daily_special is not True %}
tests if the valuedaily_special
is notTrue
.{% if value|<filter> <condition> <value> %}
.- The{% if %}
tag also supports applying filters directly on a value and then performing an evaluation. For example,{% if target_drink_list|random == user_drink %}Congratulations your drink just got selected!{% endif %}
uses therandom
filter directly in a condition.
Comparison operators are often aggregated into single statements (e.g. if...<...or...>...and...==...) and follow a certain execution precedence. Django follows the same operator precedence as Python[5]. So for example, the statement {% if drink in specials or drink == drink_of_the_day %} gets evaluated as ((drink in specials) or (drink == drink_of_the_day)) , where the internal parenthesis operations are run first, since in and == have higher precedence than or.
In Python you can alter this precedence by using explicit parenthesis in comparison statements. However, Django does not support the use of parenthesis in {% if %} tags, you must either rely on operator precedence or use nested {% if %} statements to declare the same logic produced by explicit parenthesis.
Loops
{% for %}
and{% for %}
with{% empty %}
.- The{% for %}
tag iterates over items on a dictionary, list, tuple or string variable. The{% for %}
tag syntax is{% for <reference> in <variable> %}
, wherereference
is assigned a new value from variable on each iteration.Depending on the nature of a variable there can be one or more references (e.g. for a list one reference
{% for item in list %}
, for a dictionary two references{% for key,value in dict.items %}
).In addition, it's also possible to invert the loop sequence with thereversed
keyword (e.g. {% for item in list reversed %}
).The{% for %}
tag also supports the{% empty %}
tag which is processed in case there are no iterations in a loop (i.e. the main variable is empty). Listing 3-20 illustrates a{% for %}
and a{% for %}
and{% empty %}
loop example.
Listing 3-20 Django {% for %} tag and {% for %} with {% empty %}
<ul> <ul> {% for drink in drinks %} {% for storeid,store in stores %} <li>{{ drink.name }}</li> <li><a href="/stores{{storeid}}/">{{store.name}}</a></li> {% empty %} {% endfor %} <li>No drinks, sorry</li> </ul> {% endfor %} </ul>
The {% for %}
tag
also generates a series of variables to manage the iteration
process, such as an iteration counter, a first iteration flag and a
last iteration flag. These variables can be useful when you want to
create behaviors (e.g. formatting, additional processing) on a
given iteration. Table 3-4 illustrates the {% for %}
tag variables.
Table 3-4 Django {% for %} tag variables
|
The current iteration of the loop (1-indexed) |
|
The current iteration of the loop (0-indexed) |
|
The number of iterations from the end of the loop (1-indexed) |
|
The number of iterations from the end of the loop (0-indexed) |
|
True if it's the first time through the loop |
|
True if it's the last time through the loop |
|
For nested loops, this is the parent loop to the current one |
{% ifchanged %}
.- The{% ifchanged %}
tag is a special logical tag used inside{% for %}
tags. Sometimes it's helpful to know if a loop reference has changed from one iteration to the other (e.g. to insert a new title). The argument for the{% ifchanged %}
tag is the loop reference itself (e.g.{% ifchanged drink %}{{drink}} section{% endifchanged %}
) or a part of the reference (e.g.{% ifchanged store.name %}Available in {{store.name}}{% endifchanged %}
). The{% ifchanged %}
tag also support the use of{% else %}
tag (e.g.{% ifchanged drink %}{{drink.name}}{% else %}Same old {{drink.name}} as before{% endifchanged %}
).{% cycle %}
.- The{% cycle %}
tag is used inside{% for %}
tags to iterate over a given set of strings or variables. One of the primary uses of the{% cycle %}
tag is to define CSS classes so each iteration receives a different CSS class. For example, if you want assign different CSS classes to a list so each line appears in different colors (e.g. white, grey, white, grey) you can use<li class="{% cycle 'white' 'grey' %}">
, in this manner on each loop iteration the class value alternates between white and grey. The{% cycle %}
tag can iterate sequentially over any number of strings or variables (e.g.{% cycle var1 var2 'red' %}
).By default, a
{% cycle %}
tag progresses through its values on the basis of its enclosing loop (i.e. one by one). But under certain circumstances, you may need to use a{% cycle %}
tag outside of a loop or explicitly declare how a{% cycle %
} tag advances. You can achieve this behavior by naming the{% cycle %}
tag with theas
keyword, as illustrated in listing 3-21.
Listing 3-21 Django {% cycle %} with explicit control of progression
<li class="{% cycle 'disc' 'circle' 'square' as bullettype %}">...</li> <li class="{{bullettype}}">...</li> <li class="{{bullettype}}">...</li> <li class="{% cycle bullettype %}">...</li> <li class="{{bullettype}}">...</li> <li class="{% cycle bullettype %}">...</li> # Outputs <li class="disc">...</li> <li class="disc">...</li> <li class="disc">...</li> <li class="circle">...</li> <li class="circle">...</li> <li class="square">...</li>
As you can see in listing 3-21,
the {% cycle %}
tag statement initially produces the
first value and afterwards you can continue using the cycle
reference name to output the same value. In order to advance to the
next value in the cycle, you call the {% cycle %}
once
more with the cycle reference name. A minor side-effect of the
{% cycle %}
tag is that it outputs its initial value
where it's declared, something that can be problematic if you plan
to use the cycle as a placeholder or in nested loops. To circumvent
this side-effect, you can use the silent
keyword after
the cycle reference name (e.g.{% cycle 'disc' 'circle'
'square' as bullettype silent %}
).
{% resetcycle %}
.- The{% resetcycle %}
tag is used is to re-initiate a{% cycle %}
tag to its first element. A{% cycle %}
tag always loops over its entire set of values before returning to its first one, something that can be problematic in the context of nested loops. For example, if you want to assign three color codes (e.g.{% cycle 'red' 'orange' 'yellow' %}
) to nested groups, the first group can consist of two elements that use up the first two cycle values (e.g. 'red' 'orange'), which means the second group starts on the third color code (e.g.'yellow'). In order for the second group to start with the first{% cycle %}
element again, you can use the{% resetcycle %}
tag after a nested loop iteration finishes so the{% cycle %}
tag returns to its first element.{% regroup %}
.- The{% regroup %}
tag is used to rearrange the contents of a dictionary variable into different groups. The{% regroup %}
tag avoids the need to create complex conditions inside a{% for %}
tag to achieve the desired display. The{% regroup %}
tag arranges the contents of a dictionary beforehand, making the{% for %}
tag logic simpler. Listing 3-22 illustrates a dictionary with the use of the{% regroup %}
tag along with its output.
Listing 3-22 Django {% for %} tag and {% regroup %}
# Dictionary definition stores = [ {'name': 'Downtown', 'street': '385 Main Street', 'city': 'San Diego'}, {'name': 'Uptown', 'street': '231 Highland Avenue', 'city': 'San Diego'}, {'name': 'Midtown', 'street': '85 Balboa Street', 'city': 'San Diego'}, {'name': 'Downtown', 'street': '639 Spring Street', 'city': 'Los Angeles'}, {'name': 'Midtown', 'street': '1407 Broadway Street', 'city': 'Los Angeles'}, {'name': 'Downton', 'street': '50 1st Street', 'city': 'San Francisco'}, ] # Template definition with regroup and for tags {% regroup stores by city as city_list %} <ul> {% for city in city_list %} <li>{{ city.grouper }} <ul> {% for item in city.list %} <li>{{ item.name }}: {{ item.street }}</li> {% endfor %} </ul> </li> {% endfor %} </ul> # Output San Diego Downtown : 385 Main Street Uptown : 231 Highland Avenue Midtown : 85 Balboa Street Los Angeles Downtown: 639 Spring Street Midtown: 1407 Broadway Street San Francisco Downtown: 50 1st Street
Tip The {% regroup %} tag can also use filters or properties to achieve grouping results. For example, the stores list in 3-22 is conveniently pre-ordered by city making grouping by city automatic, but if the stores list were not pre-ordered, you would need to sort the list by city first to avoid fragmented groups, you can use a dictsort filter directly (e.g.{% regroup stores|dictsort:'city' by city as city_list %}). Another possibility of the {% regroup %} tag is to use nested properties if the grouping object has them (e.g. if city had a state property, {% regroup stores by city.state as state_list %}).
Python & filter operations
{% filter %}
.- The{% filter %}
tag is used to apply Django filters to template sections. If you declare{% filter lower %}
thelower
filter is applied to all variables between this tag and the{% endfilter %}
tag -- note the filterlower
converts all content to lowercase. It's also possible to apply multiple filters to the same section using the same pipe technique to chain filters to variables (e.g.{% filter lower|center:"50" %}...variables to convert to lower case and center...{% endfilter %}
).{% with %}
.- The{% with %}
tag lets you define variables in the context of Django templates. It's useful when you need to create variables for values that aren't exposed by a Django view method or when a variable is tied to a heavyweight operation. It's also possible to define multiple variables in the same{% with %}
tag (e.g.{% with drinkwithtax=drink.cost*1.07 drinkpromo=drink.cost*0.85 %}
). Each variable defined in a{% with %}
tag is made available to the template until the{% endwith %}
tag is reached.
Django templates don't allow the inclusion of inline Python logic. In fact, the closest thing Django templates allow to inline Python logic is through the {% with %} tag which isn't very sophisticated.
The only way to make custom Python logic work in Django templates is to embed the code inside a custom Django tag or filter. This way you can place a custom Django tag or filter on a template and the Python logic runs behind the scenes. The next section describes how to create custom Django filters.
Spacing and special characters
{% autoescape %}
.- The{% autoescape %}
tag is used to escape HTML characters from a template section. The{% autoescape %}
accepts one of two argumentson
oroff
. With{% autoescape on %}
all template content between this tag and the{% endautoescape %}
tag is HTML escaped & with{% autoescape off %}
all template content between this tag and the{% endautoescape %}
tag is not escaped.
Tip If you want to enable or disable auto-escaping globally (i.e. on all templates), it's easier to disable it at the project level using the autoescape field in the OPTIONS variable in the TEMPLATES configuration, inside a project's settings.py file, as described in first section of this chapter.If you want to enable or disable auto-escaping on individual variables, you can either use the safe filter to disable auto-escaping on a single Django template variable or the escape filter to escape a single Django template variable.
{% spaceless %}
.- The{% spaceless %}
tag removes whitespace between HTML tags, including tab characters and newlines. Therefore all HTML content contained within the{% spaceless %}
and{% endspaceless %}
becomes more compact. Note the{% spaceless %}
tag only removes space between HTML tags, it does not remove space between text and HTML tags (e.g.<p> <span> my span </span> </p>
, only the space between<p>
<span>
and</span> </p>
tags is removed, the space between<span>
tags that pads themyspan
string remains).{% templatetag %}
.- The{% templatetag %}
tag is used to output reserved Django template characters. So if by any chance you want to display any of the characters{%
,%}
,{{
,}}
,{
,}
,{#
or#}
verbatim on a template you can. The{% templatetag %}
is used in conjunction with one of eight arguments to represent Django template characters.{% templatetag openblock %}
outputs{%
,{% templatetag closeblock %}
outputs%}
,{% templatetag openvariable %}
outputs{{
,{% templatetag closevariable %}
outputs}}
,{% templatetag openbrace %}
outputs{
,{% templatetag closebrace %}
outputs}
,{% templatetag opencomment %}
outputs{#
and{% templatetag closecomment %}
outputs#}
. A simpler approach is to wrap reserved Django characters with the{% verabtim %}
tag.{% verbatim %}
.- The{% verbatim %}
tag is used to isolate template content from being processed. Any content inside the{% verbatim %}
tag and{% endverbatim %}
tag is bypassed by Django. This means special characters like{{
, variable statements like{{drink}}
or JavaScript logic that uses special Django characters is ignored and rendered verbatim. If you need to output individual special characters use the{% templatetag %}
tag.{% widthratio %}
.- The{% widthratio %}
tag is used to calculate the ratio of a value to a maximum value. The{% widthratio %}
tag is helpful for displaying content that is fixed in width but requires to be scaled based on the amount of available space, such as the case with images and charts. For example, given the statement<img src="logo.gif" style="width:{% widthratio available_width image_width 100 %}%"/>
, if theavailable_width
is 75 andimage_width
is 150 it results in 0.50 multiplied by 100 which results in 50. This image's width ratio is calculated based on the available space and image size, in this case the statement is rendered as:<img src="logo.gif" style="width:50%"/>
.{% lorem %}
.- The{% lorem %}
tag is used to display random latin text, which is useful for filler on templates. The{% lorem %}
tag supports up to three parameters{% lorem [count] [method] [random] %}
. Where[count]
is a number or variable with the number of paragraphs or words to generate, if not provided the default[count]
is 1. Where[method]
is eitherw
for words,p
for HTML paragraphs orb
for plain-text paragraph blocks, if not provided the default[method]
isb
. And where the wordrandom
(if given) outputs random Latin words, instead of a common pattern (e.g. Lorem ipsum dolor sit amet...).
Template structures
{% block %}
.- The{% block %}
tag is used to define page sections that can be overridden on different Django templates. See the previous section in this chapter on how to create reusable templates for examples of this tag.{% comment "Optional explanation" %}
.- The{% comment %}
tag is used to define comment sections on Django templates. Any content placed between the{% comment %}
and{% endcomment %}
tag is bypassed by Django and doesn't appear in the final rendered web page. Note the string argument in the opening{% comment %}
tag is optional, but helps clear up the purpose of the comment.{# #}
.- The{#}
syntax can be used for a single line comment on Django templates. Any content placed between{#
and#}
in a single line is bypassed by Django and doesn't appear in the final rendered web page. Note that if the comment spans multiple lines you should use the{% comment %}
tag.{% extends %}
.- The{% extends %}
tag is used to reuse the layout of another Django template. See the previous section in this chapter on creating reusable templates for examples of this tag.{% include %}
.- The{% include %}
tag is used to embed a Django template on another Django template. See the previous section in this chapter on creating reusable templates for examples of this tag.{% load %}
.- The{% load %}
tag is used to load custom Django tags and filters. The{% load %}
tag requires one or multiple arguments to be the names of the custom Django tags or filters. The next section of this chapter describes how to create custom filters and how to use the{% load %}
tag.
Tip If you find yourself using the {% load %} tag on many templates, you may find it easier to register Django tags and filters with the builtins option in TEMPLATES so they become accessible on all templates as if they where built-in. See the first section in this chapter on template configuration for more details.
Development and testing
{% debug %}
.- The{% debug %}
tag outputs debugging information that includes template variables and imported modules. The{% debug %}
tag is useful during development and testing because it outputs 'behind the scenes' information used by Django templates.
Urls
{% url %}
.- The{% url %}
tag is used to build urls from predefined values in a project'surls.py
file. The{% url %}
tag is useful because it avoids the need to hardcode urls on templates, instead it inserts urls based on names. The{% url %}
tag accepts a url name as its first argument and url parameters as subsequent arguments.For example, if a url points to
/drinks/index/
and is nameddrinks_main
, you can use the{% url %}
to reference this url (e.g.<a href="{% url drinks_main %}"> Go to drinks home page </a>
); if a url points to/stores/1/
and is namedstores_detail
you can use the{% url %}
with an argument to reference this url (e.g.<a href="{% url stores_detail store.id %}"> Go to {{store.name}} page </a>
).The
{% url %}
tag also supports theas
keyword to define the result as a variable. This allows the result to be used multiple times or at a point other than where the{% url %}
tag is declared (e.g.{% url drink_detail drink.name as drink_on_the_day%}
...later in the template<a href="{{drink_of_the_day}}> Drink of the day </a>
). Chapter 2 describes this process to name Django url's for easier management and reverse matches in greater detail.