This document explains the language syntax of the Django template system. If you’re looking for a more technical perspective on how it works and how to extend it, see The Django template language: for Python programmers.
Django’s template language is designed to strike a balance between power and ease. It’s designed to feel comfortable to those used to working with HTML. If you have any exposure to other text-based template languages, such as Smarty or Jinja2, you should feel right at home with Django’s templates.
Philosophy
If you have a background in programming, or if you’re used to languages which mix programming code directly into HTML, you’ll want to bear in mind that the Django template system is not simply Python embedded into HTML. This is by design: the template system is meant to express presentation, not program logic.
The Django template system provides tags which function similarly to some
programming constructs – an if
tag for boolean tests, a for
tag for looping, etc. – but these are not simply executed as the
corresponding Python code, and the template system will not execute
arbitrary Python expressions. Only the tags, filters and syntax listed below
are supported by default (although you can add your own extensions to the template language as needed).
A template is simply a text file. It can generate any text-based format (HTML, XML, CSV, etc.).
A template contains variables, which get replaced with values when the template is evaluated, and tags, which control the logic of the template.
Below is a minimal template that illustrates a few basics. Each element will be explained later in this document.
{% extends "base_generic.html" %}
{% block title %}{{ section.title }}{% endblock %}
{% block content %}
<h1>{{ section.title }}</h1>
{% for story in story_list %}
<h2>
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}
Philosophy
Why use a text-based template instead of an XML-based one (like Zope’s TAL)? We wanted Django’s template language to be usable for more than just XML/HTML templates. At World Online, we use it for emails, JavaScript and CSV. You can use the template language for any text-based format.
Oh, and one more thing: making humans edit XML is sadistic!
Variables look like this: {{ variable }}
. When the template engine
encounters a variable, it evaluates that variable and replaces it with the
result. Variable names consist of any combination of alphanumeric characters
and the underscore ("_"
). The dot ("."
) also appears in variable
sections, although that has a special meaning, as indicated below.
Importantly, you cannot have spaces or punctuation characters in variable
names.
Use a dot (.
) to access attributes of a variable.
Behind the scenes
Technically, when the template system encounters a dot, it tries the following lookups, in this order:
If the resulting value is callable, it is called with no arguments. The result of the call becomes the template value.
This lookup order can cause some unexpected behavior with objects that
override dictionary lookup. For example, consider the following code snippet
that attempts to loop over a collections.defaultdict
:
{% for k, v in defaultdict.items %}
Do something with k and v here...
{% endfor %}
Because dictionary lookup happens first, that behavior kicks in and provides
a default value instead of using the intended .items()
method. In this
case, consider converting to a dictionary first.
在上面的例子中,{{ section.title }}
将会被section
对象的title
属性所替换。
If you use a variable that doesn’t exist, the template system will insert the
value of the string_if_invalid
option, which is set to ''
(the empty
string) by default.
Note that “bar” in a template expression like {{ foo.bar }}
will be
interpreted as a literal string and not using the value of the variable “bar”,
if one exists in the template context.
You can modify variables for display by using filters.
Filters look like this: {{ name|lower }}
. This displays the value of the
{{ name }}
variable after being filtered through the lower
filter, which converts text to lowercase. Use a pipe (|
) to apply a filter.
Filters can be “chained.” The output of one filter is applied to the next.
{{ text|escape|linebreaks }}
is a common idiom for escaping text contents,
then converting line breaks to <p>
tags.
Some filters take arguments. A filter argument looks like this: {{
bio|truncatewords:30 }}
. This will display the first 30 words of the bio
variable.
必须引用包含空格的过滤器参数;例如,加入一个逗号和空格的列表,您可以使用{{ list|join:", " }}
。
Django provides about sixty built-in template filters. You can read all about them in the built-in filter reference. To give you a taste of what’s available, here are some of the more commonly used template filters:
default
If a variable is false or empty, use given default. Otherwise, use the value of the variable. For example:
{{ value|default:"nothing" }}
If value
isn’t provided or is empty, the above will display
“nothing
”.
length
Returns the length of the value. This works for both strings and lists. For example:
{{ value|length }}
如果value
是['a', 'b', 'c', 'd']
,则输出将是4
。
filesizeformat
将数值处理为“人类可读”(human-readable)的文件大小格式。(例如:'13 KB'
,'4.1 MB'
,'102 bytes'
,等)。 For example:
{{ value|filesizeformat }}
If value
is 123456789, the output would be 117.7 MB
.
Again, these are just a few examples; see the built-in filter reference for the complete list.
You can also create your own custom template filters; see Custom template tags and filters.
See also
Django’s admin interface can include a complete reference of all template tags and filters available for a given site. See The Django admin documentation generator.
Tags look like this: {% tag %}
. Tags are more complex than variables: Some
create text in the output, some control flow by performing loops or logic, and
some load external information into the template to be used by later variables.
Some tags require beginning and ending tags (i.e. {% tag %} ... tag contents
... {% endtag %}
).
Django ships with about two dozen built-in template tags. You can read all about them in the built-in tag reference. To give you a taste of what’s available, here are some of the more commonly used tags:
for
Loop over each item in an array. For example, to display a list of athletes
provided in athlete_list
:
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
if
,elif
,与else
Evaluates a variable, and if that variable is “true” the contents of the block are displayed:
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
在上面的例子中,如果athlete_list
不为空,运动员的数量将会显示为{{ athlete_list|length }}
变量。 否则,如果athlete_in_locker_room_list
不为空,则显示消息“运动员应该在...之外”。 If both lists are empty,
“No athletes.” will be displayed.
You can also use filters and various operators in the if
tag:
{% if athlete_list|length > 1 %}
Team: {% for athlete in athlete_list %} ... {% endfor %}
{% else %}
Athlete: {{ athlete_list.0.name }}
{% endif %}
While the above example works, be aware that most template filters return
strings, so mathematical comparisons using filters will generally not work
as you expect. length
is an exception.
block
and extends
Again, the above is only a selection of the whole list; see the built-in tag reference for the complete list.
You can also create your own custom template tags; see Custom template tags and filters.
See also
Django’s admin interface can include a complete reference of all template tags and filters available for a given site. See The Django admin documentation generator.
To comment-out part of a line in a template, use the comment syntax: {# #}
.
For example, this template would render as 'hello'
:
{# greeting #}hello
注释可以包含任何模板代码,无论是否无效。 For example:
{# {% if foo %}bar{% else %} #}
This syntax can only be used for single-line comments (no newlines are permitted
between the {#
and #}
delimiters). If you need to comment out a
multiline portion of the template, see the comment
tag.
The most powerful – and thus the most complex – part of Django’s template engine is template inheritance. Template inheritance allows you to build a base “skeleton” template that contains all the common elements of your site and defines blocks that child templates can override.
It’s easiest to understand template inheritance by starting with an example:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
This template, which we’ll call base.html
, defines a simple HTML skeleton
document that you might use for a simple two-column page. It’s the job of
“child” templates to fill the empty blocks with content.
In this example, the block
tag defines three blocks that child
templates can fill in. All the block
tag does is to tell the template
engine that a child template may override those portions of the template.
A child template might look like this:
{% extends "base.html" %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
The extends
tag is the key here. It tells the template engine that
this template “extends” another template. When the template system evaluates
this template, first it locates the parent – in this case, “base.html”.
At that point, the template engine will notice the three block
tags
in base.html
and replace those blocks with the contents of the child
template. Depending on the value of blog_entries
, the output might look
like:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>My amazing blog</title>
</head>
<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
</div>
<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>
Note that since the child template didn’t define the sidebar
block, the
value from the parent template is used instead. Content within a {% block %}
tag in a parent template is always used as a fallback.
You can use as many levels of inheritance as needed. One common way of using inheritance is the following three-level approach:
base.html
template that holds the main look-and-feel of your
site.base_SECTIONNAME.html
template for each “section” of your
site. For example, base_news.html
, base_sports.html
. These
templates all extend base.html
and include section-specific
styles/design.This approach maximizes code reuse and makes it easy to add items to shared content areas, such as section-wide navigation.
Here are some tips for working with inheritance:
If you use {% extends %}
in a template, it must be the first template
tag in that template. Template inheritance won’t work, otherwise.
More {% block %}
tags in your base templates are better. Remember,
child templates don’t have to define all parent blocks, so you can fill
in reasonable defaults in a number of blocks, then only define the ones
you need later. It’s better to have more hooks than fewer hooks.
如果您发现自己在多个模板中复制了内容,则可能意味着您应该将该内容移动到 {% block %}
在父模板中。
如果您需要从父模板中获取块的内容,那么{{ block.super }}
将会帮助你。 This is useful
if you want to add to the contents of a parent block instead of
completely overriding it. Data inserted using {{ block.super }}
will
not be automatically escaped (see the next section), since it was
already escaped, if necessary, in the parent template.
Variables created outside of a {% block %}
using the template
tag as
syntax can’t be used inside the block. For example, this template
doesn’t render anything:
{% trans "Title" as title %}
{% block content %}{{ title }}{% endblock %}
为了更好的可读性,你可以选择给{% endblock %}
设置一个name。 For example:
{% block content %}
...
{% endblock content %}
在较大的模板中,这种方法可以帮助您查看哪些 {% block %}
标签正在关闭。
Finally, note that you can’t define multiple block
tags with the same
name in the same template. This limitation exists because a block tag works in
“both” directions. That is, a block tag doesn’t just provide a hole to fill –
it also defines the content that fills the hole in the parent. If there were
two similarly-named block
tags in a template, that template’s parent
wouldn’t know which one of the blocks’ content to use.
When generating HTML from templates, there’s always a risk that a variable will include characters that affect the resulting HTML. For example, consider this template fragment:
Hello, {{ name }}
起初,这似乎是一个无害的显示用户名字的方式,但考虑如果用户像这样输入他们名字的话会发生什么:
<script>alert('hello')</script>
With this name value, the template would be rendered as:
Hello, <script>alert('hello')</script>
…which means the browser would pop-up a JavaScript alert box!
Similarly, what if the name contained a '<'
symbol, like this?
<b>username
That would result in a rendered template like this:
Hello, <b>username
…which, in turn, would result in the remainder of the Web page being bolded!
Clearly, user-submitted data shouldn’t be trusted blindly and inserted directly into your Web pages, because a malicious user could use this kind of hole to do potentially bad things. 这种安全漏洞称作Cross Site Scripting(XSS)攻击。
To avoid this problem, you have two options:
escape
过滤器(下面介绍)运行每个不受信任的变量,这个过滤器将可能有害的HTML字符转换为无害的字符。 在Django的前几年里,这是默认的解决方案。但问题是,这样会把防止攻击的义务全部扔给你,开发者/模板作者,确保你转义了一切。 忘记转义数据是很容易的。By default in Django, every template automatically escapes the output of every variable tag. 具体来说,这五个字符是转义的:
<
is converted to <
>
is converted to >
'
(单引号)转换为'
"
(双引号)转换为"
&
is converted to &
Again, we stress that this behavior is on by default. If you’re using Django’s template system, you’re protected.
If you don’t want data to be auto-escaped, on a per-site, per-template level or per-variable level, you can turn it off in several ways.
Why would you want to turn it off? Because sometimes, template variables contain data that you intend to be rendered as raw HTML, in which case you don’t want their contents to be escaped. For example, you might store a blob of HTML in your database and want to embed that directly into your template. Or, you might be using Django’s template system to produce text that is not HTML – like an email message, for instance.
To disable auto-escaping for an individual variable, use the safe
filter:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
Think of safe as shorthand for safe from further escaping or can be
safely interpreted as HTML. In this example, if data
contains '<b>'
,
the output will be:
This will be escaped: <b>
This will not be escaped: <b>
To control auto-escaping for a template, wrap the template (or just a
particular section of the template) in the autoescape
tag, like so:
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
The autoescape
tag takes either on
or off
as its argument. At
times, you might want to force auto-escaping when it would otherwise be
disabled. Here is an example template:
Auto-escaping is on by default. Hello {{ name }}
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
The auto-escaping tag passes its effect onto templates that extend the
current one as well as templates included via the include
tag,
just like all block tags. For example:
{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}
{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}
Because auto-escaping is turned off in the base template, it will also be
turned off in the child template, resulting in the following rendered
HTML when the greeting
variable contains the string <b>Hello!</b>
:
<h1>This & that</h1>
<b>Hello!</b>
一般来说,模板作者不需要太过担心自动转义。 Developers on the Python side (people writing views and custom filters) need to think about the cases in which data shouldn’t be escaped, and mark data appropriately, so things Just Work in the template.
If you’re creating a template that might be used in situations where you’re
not sure whether auto-escaping is enabled, then add an escape
filter
to any variable that needs escaping. When auto-escaping is on, there’s no
danger of the escape
filter double-escaping data – the
escape
filter does not affect auto-escaped variables.
As we mentioned earlier, filter arguments can be strings:
{{ data|default:"This is a string literal." }}
All string literals are inserted without any automatic escaping into the
template – they act as if they were all passed through the safe
filter. The reasoning behind this is that the template author is in control of
what goes into the string literal, so they can make sure the text is correctly
escaped when the template is written.
This means you would write
{{ data|default:"3 < 2" }}
…rather than:
{{ data|default:"3 < 2" }} {# Bad! Don't do this. #}
This doesn’t affect what happens to data coming from the variable itself. The variable’s contents are still automatically escaped, if necessary, because they’re beyond the control of the template author.
Most method calls attached to objects are also available from within templates. This means that templates have access to much more than just class attributes (like field names) and variables passed in from views. For example, the Django ORM provides the “entry_set” syntax for finding a collection of objects related on a foreign key. Therefore, given a model called “comment” with a foreign key relationship to a model called “task” you can loop through all comments attached to a given task like this:
{% for comment in task.comment_set.all %}
{{ comment }}
{% endfor %}
Similarly, QuerySets provide a count()
method
to count the number of objects they contain. Therefore, you can obtain a count
of all comments related to the current task with:
{{ task.comment_set.all.count }}
And of course you can easily access methods you’ve explicitly defined on your own models:
class Task(models.Model):
def foo(self):
return "bar"
{{ task.foo }}
Because Django intentionally limits the amount of logic processing available in the template language, it is not possible to pass arguments to method calls accessed from within templates. Data should be calculated in views, then passed to templates for display.
Certain applications provide custom tag and filter libraries. To access them in
a template, ensure the application is in INSTALLED_APPS
(we’d add
'django.contrib.humanize'
for this example), and then use the load
tag in a template:
{% load humanize %}
{{ 45000|intcomma }}
In the above, the load
tag loads the humanize
tag library, which then
makes the intcomma
filter available for use. If you’ve enabled
django.contrib.admindocs
, you can consult the documentation area in your
admin to find the list of custom libraries in your installation.
The load
tag can take multiple library names, separated by spaces.
Example:
{% load humanize i18n %}
See Custom template tags and filters for information on writing your own custom template libraries.
When you load a custom tag or filter library, the tags/filters are only made available to the current template – not any parent or child templates along the template-inheritance path.
For example, if a template foo.html
has {% load humanize %}
, a child
template (e.g., one that has {% extends "foo.html" %}
) will not have
access to the humanize template tags and filters. The child template is
responsible for its own {% load humanize %}
.
This is a feature for the sake of maintainability and sanity.
See also
Jan 17, 2018