Jinja built-in filters and tests (like Django filters)
The Jinja documentation makes an explicit difference between what it calls filters and tests. The only difference is Jinja tests are used to evaluate conditions and Jinja filters are used to format or transform values. In Django there is no such naming difference and an equivalent Jinja test in Django is simply called a Django filter.
The syntax to apply Jinja filters
to template variables is the vertical bar character |
, also called a 'pipe' in Unix environments
(e.g.{{variable|filter}}
). It's worth mentioning you
can apply multiple filters to the same variable
(e.g.{{variable|filter|filter}}
). The syntax to apply
Jinja tests uses the is
keyword along with a regular
conditional to evaluate the validity of a test (e.g. {% if
variable is divisibleby 10 %}do something{% endif %}
).
In the upcoming sections, I'll add the reference (Test) to indicate it's referring to a Jinja test vs. a Jinja filter. I'll also classify each Django built-in filter & test into functional sections so they are easier to identify. I'll define the broadest category 'Strings, lists, dictionaries, numbers and objects' for filters and tests that pplicable for most scenarios and then more specialized sections for each data type, including: 'String and lists', 'Dictionaries and objects', Strings, Numbers, Spacing and special characters, Development and testing and Urls.
Strings, lists, dictionaries, numbers and objects
default
ord
.- Thedefault
ord
filter is used to specify a default value if a variable is undefined or is false (i.e. it doesn't exist or is empty). For example, the filter statement{{variable|default("no value")}}
outputsno value
only if the variable is undefined, otherwise it outputs the variable value. If in addition you want to provide a default value for a variable that evaluates to false, is None or is an empty string, you have to addtrue
as a second filter parameter (e.g.{{variable|default("no value",true)}}
outputsno value
if the variable is undefined, false, is None or is an empty string).defined
(Test).- Thedefined
test is used to check if a variable is defined, if a variable is defined this tests return true. Listing 4-19 illustrates an example of thedefined
test.
Listing 4-19 Jinja defined test
{% if variable is defined %} value of variable: {{ variable }} {% else %} variable is not defined {% endif %}
none
(Test).- Thenone
test is used to check if a variable is none, if a variable is None this tests return true.length
orcount
.- Thelength
filter is used to obtain the length of a value. For example, if a variable containslatte
the filter statement{{variable|length}}
outputs 5. For a list variable that contains['a','e','i']
the filter statement{{variable|length}}
outputs 3.equalto
(Test).- Theequalto
test checks if an object has the same value as another object. For example{% if coffee.price is equalto 1.99 %} coffee prices equals 1.99 {% endif %}
. This works just like the==
, but is more helpful when used with other filters such asselectattr
(e.g.{{ users|selectattr("email", "equalto", "webmaster@coffeehouse.com") }}
, gets users with emailwebmaster@coffeehouse.com
).string
(Test).- Thestring
test checks if a variable is a string (e.g.{% if variable is string %}Yes, the variable is a string!{% endif %}
).number
(Test).- Thenumber
test returns true if a variable is a number.iterable
(Test).- Theiterable
test checks if it's possible to iterate over an object.sequence
(Test).- Thesequence
test checks if the object is a sequence (e.g. a generator).mapping
(Test).- Themapping
test checks if the object is a mapping (e.g. a dictionary).callable
(Test).- The callable test verifies if an object is callable. In Python a function, classes and object instances with a __call__ method are callables.sameas
(Test).- Thesameas
test verifies if an object points to the same memory address than another object.eq
orequalto
(or==
) (Test).- Theeq
orequalto
tests verify if object is equal.ne
(or!=
) (Test).- Thene
test verifies if an object is not equal.lt
orlessthan
(or<
) (Test).- Thelt
orlessthan
tests verify if an object is less than.le
(or<=
) (Test).- Thele
test verifies if an object is less than or equal.gt
orgreaterthan
(or>
) (Test).- Thegt
orgreaterthan
tests verify if an object is greater than.ge
(or<=
) (Test).- Thege
test verifies if an object is greater than or equal.in
(Test).- Thein
test verifies if a given variable contains a value.boolean
(Test).- Theboolean
test returns true if a variable is a boolean.false
(Test).- Thefalse
test returns true if a variable is false.true
(Test).- Thetrue
test returns true if a variable is true.integer
(Test).- Theinteger
test returns true if a variable is an integer.float
(Test).- Thefloat
test returns true if a variable is a float.
Strings and lists
reverse
.- The reverse filter is used to get inverse representation of a value. For example, if a variable containslatte
the filter statement{{variable|reverse}}
generatesettal
.first
.- Thefirst
filter returns the first item in a list or string. For example, for a list variable that contains['a','e','i','o','u']
the filter statement{{variable|first}}
outputsa
.join
.- Thejoin
filter joins a list with a string. Thejoin
filter works just like Python'sstr.join(list)
. For example, for a list variable that contains['a','e','i','o','u']
the filter statement{{variable|join("--)}}
outputsa--e--i--o--u
. Thejoin
filter also supports joining certain attributes of an object (e.g.{{ users|join(', ', attribute='username') }}
)last
.- Thelast
filter returns the last item in a list or string. For example, for a list variable that contains['a','e','i','o','u']
the filter statement{{variable|last}}
outputsu
.map
.- Themap
filter allows you to apply a filter or look up attributes, just like the standard Pythonmap
method. For example, if you have list of users but are only interested in outputting a list of usernames a map is helpful (e.g.{{ users|map(attribute='username')|join(', ') }}
). In addition, it's also possible to invoke a filter by passing the name of the filter and the arguments afterwards (e.g.{{ titles|map('lower')|join(', ') }}
applies thelower
filter to all the elements intitles
and then joins the items separated by a comma).max
.- Themax
filter selects the largest item in a variable. For example, for a list variable that contains[1,2,3,4,5]
the statement{{ variable|max }}
returns5
.min
.- Themin
filter selects the smallest item in a variable. For example, for a list variable that contains[1,2,3,4,5]
the statement{{ variable|min }}
returns1
.random
.- Therandom
filter returns a random item in a list. For example, for a list variable that contains['a','e','i','o','u']
the filter statement{{variable|random}}
could outputa
,e
,i
,o
oru
.reject
.- Thereject
filter removes elements that pass a certain test -- see bullets in this chapter section marked as (Test) for acceptable values. For example, for a list variable that contains[1,2,3,4,5]
the loop statement with this filter{% for var in variable|reject("odd") %}{{var}}{% endfor %}
-- whereodd
is the Jinja test -- rejects elements that are odd and thus its output is2
and4
.select
.- Theselect
filter selects elements that pass a certain test -- see bullets in this chapter section marked as (Test) for acceptable values. For example, for a list variable that contains[1,2,3,4,5]
the loop statement with this filter{% for var in variable|select("odd") %}{{var}}{% endfor %}
-- whereodd
is the Jinja test -- selects elements that are odd and thus its output is1
,3
and5
.slice
.- Theslice
filter returns a slice of lists. For example, for a variable that contains["Capuccino"]
the filter statement{% for var in variable|slice(4) %}{{var}}{% endfor %}
outputs['C', 'a', 'p'],['u', 'c'],['c', 'i'], ['n', 'o']
. It's possible to use thefill_with
as a second argument -- which defaults to None -- so all segments contain the same number of elements filled with a given value. For example,{% for var in variable|slice(4,'FILLER') %}{{var}}{% endfor %}
outputs:['C', 'a', 'p'],['u', 'c','FILLER'],['c', 'i','FILLER'], ['n', 'o','FILLER']
.batch
.- Thebatch
filter returns a batch of lists. For example, a variable that contains["Capuccino"]
the filter statement{% for var in variable|batch(4) %}{{var}}{% endfor %}
outputs['C', 'a', 'p', 'u'],['c', 'c', 'i', 'n'],['o']
. It's possible to use thefill_with
as a second argument -- which defaults to None -- so all segments contain the same number of elements filled with a given value. For example,{% for var in variable|slice(4,'FILLER') %}{{var}}{% endfor %}
outputs:['C', 'a', 'p', 'u'],['c', 'c', 'i', 'n'],['o','FILLER','FILLER','FILLER']
.sort
.- Thesort
filter sorts elements by ascending order. For example, if a variable contains['e','u','a','i','o']
the statement{{variable|sort}}
outputs['a','e','i','o','u']
. It's possible to indicate descending order by setting the first argument to true (e.g.{{variable|sort(true)}}
outputs['u','o','i','e','a']
). In addition, if a list is made up strings, a second argument can be used to indicate case sensitiveness -- which is disabled by default -- to perform the sort operation (e.g.{{variable|sort(true,true)}}
). Finally, if a list is composed of objects, it's also possible to specify the sort operation on a given attribute (e.g.variable|sort(attribute='date')
to sort the elements based on thedate
attribute).unique
.- Theunique
filter returns unique values. For example, if a variable contains['Python','PYTHON','Python','JAVASCRIPT', 'JavaScript']
the statement{{variable|unique|list}}
outputs['Python','JAVASCRIPT']
. By default, theunique
filter is case insensitive and returns the first unique match it finds. It's possible to perfom case sensitive unique matching using thecase_sensitive
argument (e.g.{{variable|unique(case_sensitive=True)|list}}
returns['Python', 'PYTHON', 'JAVASCRIPT', 'JavaScript']
).
Dictionaries and objects
dictsort
.- Thedictsort
filter sorts a dictionary by key, case insensitive. For example, if a variable contains{'name':'Downtown','city':'San Diego','state':'CA'}
the filter{% with newdict=variable|dictsort %}
thenewdict
variable is assigned the dictionary{'city':'San Diego','name':'Downtown','state':'CA'}
. In addition, thedictsort
can accept three arguments:case_sensitive
to indicate case sensitive/insensitive order,by
to specify sorting by key or value andreverse
to specify reverse ordering. The defaultdictsort
behavior is case insensitive, sort by key and natural(provided) order (e.g.variable|dictsort
). To alter the defaultdictsort
behavior, you can assign:case_sensitive
aTrue
orFalse
(Default) value;by
a'value'
or'key'
(Default) value; andreverse
aTrue
orFalse
(Default) value.attr
.- Theattr
filter returns the attribute of an object (e.g.{{coffeehouse.city}}
outputs thecity
attribute value of thecoffeehouse
object). Note theattr
filter only attempts to look up an attribute and not an item (e.g. ifcoffeehouse
is a dictionary andcity
is a key item it won't be found). Alternatively, you can just use the standard Python syntaxvariable.name
-- which first attempts to locate an attribute calledname
onvariable
, then thename
item onvariable
or if nothing matches an undefined object is returned -- orvariable['name']
-- which first attempts to locate thename
item onvariable
, then an attribute calledname
onvariable
or if nothing matches an undefined object is returned.rejectattr
.- Therejectattr
filter removes objects that don't contain an attribute or objects for which a certain attribute doesn't pass a test -- see bullets in this chapter section marked as (Test) for acceptable values. For example,{% for ch in coffeehouses|rejectattr("closedon") %}
generates a loop forcoffeehouse
objects that don't have theclosedon
attribute or{% for u in users|rejectattr("email", "none") %}
generates a loop foruser
objects that don't haveemail
None -- note the second argumentnone
represents the test.selectattr
.- Theselectattr
filter selects objects that contain an attribute or objects for which a certain attribute passes a test -- see bullets in this chapter section marked as (Test) for acceptable values. For example,{% for u in users|selectattr("superuser") %}
generates a loop foruser
objects that have thesuperuser
attribute or{% for u in users|selectattr("email", "none") %}
generates a loop foruser
objects that haveemail
None -- note the second argumentnone
represents the test.groupby
.- Thegroupby
filter is used to rearrange the contents of a list of dictionaries or objects into different group object sequences by a common attribute. Listing 4-20 illustrates an example of thegroupby
filter.
Listing 4-20. Jinja groupby filter
# 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'}, ] <ul> {% for group in stores|groupby('city') %} <li>{{ group.grouper }} <ul> {% for item in group.list %} <li>{{ item.name }}: {{ item.street }}</li> {% endfor %} </ul> </li> {% endfor %} </ul> # Output Los Angeles Downtown: 639 Spring Street Midtown: 1407 Broadway Street San Diego Downtown : 385 Main Street Uptown : 231 Highland Avenue Midtown : 85 Balboa Street San Francisco Downtown: 50 1st Street # Alternate shortcut syntax, produces same output <ul> {% for grouper, list in stores|groupby('city') %} <li>{{ grouper }} <ul> {% for item in list %} <li>{{ item.name }}: {{ item.street }}</li> {% endfor %} </ul> </li> {% endfor %} </ul>
tojson
.- Thetojson
filter outputs data structures to JavaScript Object Notation(JSON) (e.g.{{variable|tojson}}
). Thetojson
filter accepts theindent
argument -- which is set toNone
-- to generate pretty output by a given number of spaces (e.g.{{variable|tojson(indent=2)}}
) generates output indented with two spaces).
Tip You can globally set options for the tojson filter through Jinja policies, described in the last section of this chapter.
Strings
capitalize
.- Thecapitalize
filter capitalizes the first character of a string variable. For example, if a variable containshello world
the filter statement{{variable|capitalize}}
outputsHello world
.list
.- Thelist
filter is used to return a list of characters. For example, if a variable containslatte
the filter statement{{variable|list}}
generates['l','a','t','t','e']
.lower
.- Thelower
filter converts all values of a string variable to lowercase. For example, if a variable containsHello World
the filter statement{{variable|lower}}
outputshello world
.lower
(Test).- Thelower
test returns true if a variable is lower cased. For example,{% if variable is lower %}Yes, the variable is lowercase!{% endif %}
outputs the statement ifvariable
is lower casedreplace
.- Thereplace
filter works just like Python's standardreplace
string. The first argument is the sub-string that should be replaced, the second is the replacement string. If the optional third argument amount is given, only this amount of occurrences are replaced. For example{{ "Django 1.8"|replace("1.8", "1.9") }}
outputsDjango 1.9
and{{"oooh Django!"|replace("o", "",2) }}
outputsoh Django!
.string
.- Thestring
filter makes a string unicode if it isn't already.title
.- Thetitle
filter converts all first character values of a string variable to uppercase. For example, if a variable containshello world
the filter statement{{variable|title}}
outputsHello World
.upper
.- Theupper
filter converts all values of a string variable to uppercase. For example, if a variable containsHello World
the filter statement{{variable|upper}}
outputsHELLO WORLD
.upper
(Test).- Theupper
test returns true if a variable is upper cased. For example,{% if variable is upper %}Yes, the variable is uppercase!{% endif %}
outputs the statement ifvariable
is uppercase.wordcount
.- Thewordcount
filter counts the words in a string. For example, if a variable containsCoffeehouse started as a small store
the filter statement{{variable|wordcount}}
outputs 6.
Numbers
abs
.- Theabs
return the absolute value of the number argument. For example, if a variable contains-5
the filter statement{{variable|abs}}
outputs5
.filesizeformat
.-Thefilesizeformat
filter converts a number of bytes into a friendly file size string. For example, if a variable contains 250 the filter statement{{variable|filesizeformat}}
outputs 250 Bytes, if it contains 2048 the output is 2 kB, if it contains 2000000000 the output is 2.0 GB. By default, decimal prefixes are used (e.g. Giga, Mega, Kilo), if you pass an additional boolean parameter with true (e.g.{{variable|filesizeformat(true)}}
) then binary prefixes are used (e.g. Gibi, Mebi, Kibi)float
.- Thefloat
filter converts a value into a floating-point number. If the conversion doesn't work it returns 0.0 or a custom value argument (e.g.variable|float("It didn't work")
returns"It didn't work"
ifvariable
can't be converted to a floating-point number).int
.- Theint
filter converts a value into an integer. If the conversion doesn't work it returns 0 or a custom value specified as the first argument to the filter -- just like thefloat
filter. You can also override the default base 10 with a second filter argument, which handles input with prefixes such as 0b, 0o and 0x for bases 2, 8 and 16 respectively (e.g.{{'0b001111'|int(0,2)}}
a base 2 number outputs 15.round
.- Theround
filter rounds a number to a given precision, where the first argument is the precision -- which defaults to 0 -- and the second argument is a rounding method -- which defaults to 'common
' rounding either up or down. For example,{{ 33.55|round }}
assumes 'common
' rounding to output34.0
). In addition to 'common
', it's also possible to use 'ceil
' to always round up or 'floor
' to always round down (e.g.{{ 33.55|round(1,'floor') }}
outputs33.5
). Note that even if rounded to the default 0 precision, a float is returned. If you need an integer you can apply theint
filter (e.g.{{ 33.55|round|int }}
outputs34
).sum
.- Thesum
filter returns the sum of a sequence of numbers, plus the value provided with the start parameter which defaults to 0. In addition, it's also possible to sum certain attributes of a list of objects{{ items|sum(attribute='price') }}
.divisibleby
(Test).- Thedivisibleby
test checks if a variable is divisible by a given number. For example, if a variable contains 20 the filter statement{% if variable is divisibleby(5) %}Variable is divisible by 5!{% endif %}
outputs the conditional statement.even
(Test).- Theeven
test checks if a number is even.odd
(Test).- Theodd
test checks if a number is odd.
Spacing and special characters
center
.- Thecenter
filter center aligns a value and pads it with additional white space characters until it reaches the given argument of characters. For example, if a variable containsmocha
the filter statement{{variable|center(width="15")}}
outputs" mocha "
.escape
ore
.- Theescape
ore
filter escapes HTML characters from a value. Specifically with theescape
filter:<
is converted to<,>
is converted to>
,'
(single quote) is converted to'
,"
(double quote) is converted to"
, and&
is converted to&
.escaped
(Test).- The escaped test checks if a value is escaped.forceescape
.- Theforceescape
filter escapes HTML characters from a value just like the escape filter. The difference between both filters is theforceescape
filter is applied immediately and returns a new and escaped string. This is useful in the rare cases where you need multiple escaping or want to apply other filters to the escaped results. Normally, you'll use theescape
filter.format
.- Theformat
filter is used to apply Python string formatting to a variable. For example, the statement{{ "%s and %s"|format("Python", "Django!") }}
outputsPython and Django!
.indent
.- Theindent
filter is used to output a string with each line except the first one indented with four spaces. It's possible to change the number of spaces and the indentation of the first line with additional filter arguments (e.g.{{ textvariable|indent(2, true) }}
the2
indicates two spaces andtrue
indicates to indent the first line.safe
.- Thesafe
filter marks a string as not requiring further HTML escaping. When this filter is used with an environment without automatic escaping it has no effect.striptags
.- Thestriptags
filter removes all HTML tags from a value. For example, if a variable contains<b>Coffee</b>house, the <i>best</i> <span>drinks</span>
the filter statement{{variable|striptags}}
outputsCoffeehouse, the best drinks
.trim
.- Thetrim
filter is used to strip leading and trailing whitespace just like Python's stringstrip()
method. By default,trim
strips leading and trailing whitespace, but it's possible to strip specific characters by passing a string argument (e.g.variable|strip("#")
strips leading and trailing#
fromvariable
).truncate
.- Thetruncate
filter truncates a string to a given number of characters -- defaulting to 255 characters -- and appends an ellipsis sequence. For example, if a variable containsCoffeehouse started as a small store
the filter statement{{variable|truncate(20)}}
outputsCoffeehouse ...
, keeping up until character number 20 and then discarding the last full word, finally adding the ellipsis. You can addtrue
as a second argument so the string is cut at an exact length (e.g.{{variable|truncate(20,true)}}
outputsCoffeehouse start...
including the ellipsis characters). It's possible to provide a different symbol than an ellipsis passing a second parameter (e.g.{{variable|truncate(20,true,"!!!")}}
would output !!! instead of an elipsis). And finally, thetruncate
filter accepts a fourth argumentleeway
to specify a string tolerance in characters -- which defaults to 5 -- to avoid truncating strings (e.g. this avoids truncating words with less than 5 characters).
Tip You can globally set the leeway value for the truncate filter through Jinja policies, described in the last section of this chapter.
wordwrap
.- Thewordwrap
filter wraps words at a given character line length argument. By default, the wrapping occurs after 79 characters which can be overridden providing a first argument with the number of characters. If you set a second parameter to false, Jinja does not split words longer than the wrapping character length. In addition, wrapping generates a newline character as defined in the environment -- generally the \n character -- but this can be changed by specifying thewrapstring
keyword argument (e.g.{{variable|wordwrap(40,true,'-')
uses a hyphen as the wrapping newline character). Finally, a fourth argument can be passed to thewordwrap
filter to indicate if breaks should be applied on hyphens, which by default is true, it's helpful to set this option to false when dealing with long words that have hyphens that shouldn't wrap (e.g. site urls). Listing 4-21 illustrates an example of thewordwrap
filter.
Listing 4-21. Jinja wordwrap filter
# Variable definition Coffeehouse started as a small store # Template definition with wordwrap filter for every 12 characters {{variable|wordwrap(12)}} # Output Coffeehouse started as a small store
xmlattr
.- Thexmlattr
filter is used to create an SGML/XML attribute string based on the items in a dictionary or object. Once you create a dictionary structure containing attribute names and reference values, you pass it through thexmlattr
filter to generate the attribute string. By default, all values that are neither none or undefined are automatically escaped, but you can override this behavior by passing false as the first filter argument. Listing 4-22 illustrates an example of thexmlattr
filter.
Listing 4-22. Django xmlattr filter
# Variable definition {% set stores = [ {'id':123,'name': 'Downtown', 'street': '385 Main Street', 'city': 'San Diego'}, {'id':243,'name': 'Uptown', 'street': '231 Highland Avenue', 'city': 'San Diego'}, {'id':357,'name': 'Midtown', 'street': '85 Balboa Street', 'city': 'San Diego'}, {'id':478,'name': 'Downtown', 'street': '639 Spring Street', 'city': 'Los Angeles'}, {'id':529,'name': 'Midtown', 'street': '1407 Broadway Street', 'city': 'Los Angeles'}, {'id':653,'name': 'Downton', 'street': '50 1st Street', 'city': 'San Francisco'}, ] %} # Template definition <ul> {% for store in stores %} <li {{ {'id':'%d'|format(store.id),'class':'%s'|format(store.city|lower|replace(' ','-')) }|xmlattr }}> {{store.city}} {{store.name}} </li> {% endfor %} </ul> # Output <ul> <li id="123" class="san-diego"> San Diego Downtown</li> <li id="243" class="san-diego"> San Diego Uptown</li> <li id="357" class="san-diego"> San Diego Midtown</li> <li id="478" class="los-angeles"> Los Angeles Downtown</li> <li id="529" class="los-angeles"> Los Angeles Midtown</li> <li id="653" class="san-francisco"> San Francisco Downton</li> </ul>
Development and testing
pprint
.- Thepprint
filter is a wrapper for Python'spprint.pprint()
. Thepprint
filter is useful during development and testing because it outputs the formatted representation of an object. By default, thepprint
filter is not verbose but you can make it verbose passing it the true argument (e.g.{{variable|pprint(true)}}
).
Urls
urlencode
.- Theurlencode
filter escapes a value for use in a URL. For example, if a variable containshttp://localhost/drinks?type=cold&size=large
the filter statement{{variable|urlencode}}
outputshttp%3A//localhost/drinks%3Ftype%3Dcold%26size%3Dlarge
.urlize
.- Theurlize
filter converts text URLs into clickable HTML links. You can pass the filter an additional integer to shorten the visible url (e.g.{{ variable|urlize(40)}}
links are shortened to 40 characters plus an ellipsis). It's also possible to add a second argument as a boolean to make the urls "nofollow" (e.g.{{ variable|urlize(40, true)}}
links are shortened to 40 characters and defined with rel="nofollow"). Finally, it's also possible to add the target argument to define a link target (e.g.{{ variable|urlize(40, target="_blank")}}
links are shortened to 40 characters and open in a new window).
Tip You can globally set rel and target values for the the urlize filter through Jinja policies, described in the last section of this chapter.