============================ The Django template language ============================ 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 :doc:`/ref/templates/api`. 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. .. admonition:: 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 :ttag:`if` tag for boolean tests, a :ttag:`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 :doc:`your own extensions ` to the template language as needed). .. _`The Django template language: For Python programmers`: ../templates_python/ .. _Smarty: https://www.smarty.net/ .. _Jinja2: https://palletsprojects.com/p/jinja/ Templates ========= A template is 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. .. code-block:: html+django {% extends "base_generic.html" %} {% block title %}{{ section.title }}{% endblock %} {% block content %}
{{ story.tease|truncatewords:"100" }}
{% endfor %} {% endblock %} .. admonition:: 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. You can use the template language for any text-based format such as emails, JavaScript and CSV. .. _template-variables: Variables ========= 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 (``"_"``) but may not start with an underscore, and may not be a number. 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. .. admonition:: Behind the scenes Technically, when the template system encounters a dot, it tries the following lookups, in this order: * Dictionary lookup * Attribute or method lookup * Numeric index lookup 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``: .. code-block:: html+django {% 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. In the above example, ``{{ section.title }}`` will be replaced with the ``title`` attribute of the ``section`` object. 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. Variable attributes that begin with an underscore may not be accessed as they're generally considered private. Filters ======= 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 :tfilter:`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 ```` 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.
Filter arguments that contain spaces must be quoted; for example, to join a
list with commas and spaces you'd use ``{{ list|join:", " }}``.
Django provides about sixty built-in template filters. You can read all about
them in the :ref:`built-in filter reference {{ entry.body }} This is my first entry. This is my second entry. {{ user.bio }} {{ user.bio }}
{% for athlete in athlete_list %}
:ttag:`if`, ``elif``, and ``else``
Evaluates a variable, and if that variable is "true" the contents of the
block are displayed:
.. code-block:: html+django
{% 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 %}
In the above, if ``athlete_list`` is not empty, the number of athletes
will be displayed by the ``{{ athlete_list|length }}`` variable. Otherwise,
if ``athlete_in_locker_room_list`` is not empty, the message "Athletes
should be out..." will be displayed. If both lists are empty,
"No athletes." will be displayed.
You can also use filters and various operators in the :ttag:`if` tag:
.. code-block:: html+django
{% 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. :tfilter:`length` is an exception.
:ttag:`block` and :ttag:`extends`
Set up `template inheritance`_ (see below), a powerful way
of cutting down on "boilerplate" in templates.
Again, the above is only a selection of the whole list; see the :ref:`built-in
tag reference {{ entry.title }}
Entry one
Entry two
{{ user.name }}
Authors
{% for user in authors %}
{% partial user-info %}
{% endfor %}
Editors
{% for user in editors %}
{% partial user-info %}
{% endfor %}
{% endblock %}
The partial content is rendered each time the named partial is used, with the
current template context.
.. _template-partials-inline:
Inline partials
---------------
A template fragment can be defined and rendered in-place using the ``inline``
argument. This defines the partial for later reuse while also rendering it
immediately at its definition:
.. code-block:: html+django
{# Define and render immediately. #}
{% partialdef user-info inline %}
{{ user.name }}
Featured Author of the Month
{% partial user-info %}
{% endwith %}
.. _next section: #automatic-html-escaping
.. _automatic-html-escaping:
Automatic HTML escaping
=======================
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:
.. code-block:: html+django
Hello, {{ name }}
At first, this seems like a harmless way to display a user's name, but consider
what would happen if the user entered their name as this:
.. code-block:: html+django
With this name value, the template would be rendered as:
.. code-block:: html+django
Hello,
...which means the browser would pop-up a JavaScript alert box!
Similarly, what if the name contained a ``'<'`` symbol, like this?
.. code-block:: html
username
That would result in a rendered template like this:
.. code-block:: html+django
Hello, username
...which, in turn, would result in the remainder of the web page being in bold!
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. This type of security exploit is called a
`Cross Site Scripting`_ (XSS) attack.
To avoid this problem, you have two options:
* One, you can make sure to run each untrusted variable through the
:tfilter:`escape` filter (documented below), which converts potentially
harmful HTML characters to unharmful ones. This was the default solution
in Django for its first few years, but the problem is that it puts the
onus on *you*, the developer / template author, to ensure you're escaping
everything. It's easy to forget to escape data.
* Two, you can take advantage of Django's automatic HTML escaping. The
remainder of this section describes how auto-escaping works.
By default in Django, every template automatically escapes the output
of every variable tag. Specifically, these five characters are
escaped:
* ``<`` is converted to ``<``
* ``>`` is converted to ``>``
* ``'`` (single quote) is converted to ``'``
* ``"`` (double quote) 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.
.. _Cross Site Scripting: https://en.wikipedia.org/wiki/Cross-site_scripting
How to turn it off
------------------
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.
For individual variables
~~~~~~~~~~~~~~~~~~~~~~~~
To disable auto-escaping for an individual variable, use the :tfilter:`safe`
filter:
.. code-block:: html+django
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 ``''``,
the output will be:
.. code-block:: html+django
This will be escaped: <b>
This will not be escaped:
For template blocks
~~~~~~~~~~~~~~~~~~~
To control auto-escaping for a template, wrap the template (or a particular
section of the template) in the :ttag:`autoescape` tag, like so:
.. code-block:: html+django
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
The :ttag:`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:
.. code-block:: html+django
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 :ttag:`include` tag,
just like all block tags. For example:
.. code-block:: html+django
:caption: ``base.html``
{% autoescape off %}
{% block title %}{% endblock %}
{% block content %}
{% endblock %}
{% endautoescape %}
.. code-block:: html+django
:caption: ``child.html``
{% 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 ``Hello!``:
.. code-block:: html+django
This & that
Hello!
Notes
-----
Generally, template authors don't need to worry about auto-escaping very much.
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 :tfilter:`escape` filter
to any variable that needs escaping. When auto-escaping is on, there's no
danger of the :tfilter:`escape` filter *double-escaping* data -- the
:tfilter:`escape` filter does not affect auto-escaped variables.
.. _string-literals-and-automatic-escaping:
String literals and automatic escaping
--------------------------------------
As we mentioned earlier, filter arguments can be strings:
.. code-block:: html+django
{{ 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 :tfilter:`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 :
.. code-block:: html+django
{{ data|default:"3 < 2" }}
...rather than:
.. code-block:: html+django
{{ 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.
.. _template-accessing-methods:
Accessing method calls
======================
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 :ref:`"entry_set"