123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786 |
- ============================
- 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
- </howto/custom-template-tags>` 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 %}
- <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 %}
- .. 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 ``<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.
- 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 <ref-templates-builtins-filters>`.
- To give you a taste of what's available, here are some of the more commonly
- used template filters:
- :tfilter:`default`
- If a variable is false or empty, use given default. Otherwise, use the
- value of the variable. For example:
- .. code-block:: html+django
- {{ value|default:"nothing" }}
- If ``value`` isn't provided or is empty, the above will display
- "``nothing``".
- :tfilter:`length`
- Returns the length of the value. This works for both strings and lists.
- For example:
- .. code-block:: html+django
- {{ value|length }}
- If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``.
- :tfilter:`filesizeformat`
- Formats the value like a "human-readable" file size (i.e. ``'13 KB'``,
- ``'4.1 MB'``, ``'102 bytes'``, etc.). For example:
- .. code-block:: html+django
- {{ value|filesizeformat }}
- If ``value`` is 123456789, the output would be ``117.7 MB``.
- Again, these are just a few examples; see the :ref:`built-in filter reference
- <ref-templates-builtins-filters>` for the complete list.
- You can also create your own custom template filters; see
- :doc:`/howto/custom-template-tags`.
- .. seealso::
- Django's admin interface can include a complete reference of all template
- tags and filters available for a given site. See
- :doc:`/ref/contrib/admin/admindocs`.
- Tags
- ====
- 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 :ref:`built-in tag reference <ref-templates-builtins-tags>`. To give
- you a taste of what's available, here are some of the more commonly used
- tags:
- :ttag:`for`
- Loop over each item in an array. For example, to display a list of athletes
- provided in ``athlete_list``:
- .. code-block:: html+django
- <ul>
- {% for athlete in athlete_list %}
- <li>{{ athlete.name }}</li>
- {% endfor %}
- </ul>
- :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 <ref-templates-builtins-tags>` for the complete list.
- You can also create your own custom template tags; see
- :doc:`/howto/custom-template-tags`.
- .. seealso::
- Django's admin interface can include a complete reference of all template
- tags and filters available for a given site. See
- :doc:`/ref/contrib/admin/admindocs`.
- .. _template-comments:
- Comments
- ========
- To comment-out part of a line in a template, use the comment syntax: ``{# #}``.
- For example, this template would render as ``'hello'``:
- .. code-block:: html+django
- {# greeting #}hello
- A comment can contain any template code, invalid or not. For example:
- .. code-block:: html+django
- {# {% 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 :ttag:`comment` tag.
- .. _template-inheritance:
- Template inheritance
- ====================
- 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.
- Let's look at template inheritance by starting with an example:
- .. code-block:: html+django
- <!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 an HTML skeleton
- document that you might use for a two-column page. It's the job of "child"
- templates to fill the empty blocks with content.
- In this example, the :ttag:`block` tag defines three blocks that child
- templates can fill in. All the :ttag:`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:
- .. code-block:: html+django
- {% 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 :ttag:`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 :ttag:`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:
- .. code-block:: html+django
- <!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:
- * Create a ``base.html`` template that holds the main look-and-feel of your
- site.
- * Create a ``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.
- * Create individual templates for each type of page, such as a news
- article or blog entry. These templates extend the appropriate section
- template.
- This approach maximizes code reuse and helps to add items to shared content
- areas, such as section-wide navigation.
- Here are some tips for working with inheritance:
- * If you use :ttag:`{% extends %}<extends>` in a template, it must be the first template
- tag in that template. Template inheritance won't work, otherwise.
- * More :ttag:`{% block %}<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.
- * If you find yourself duplicating content in a number of templates, it
- probably means you should move that content to a ``{% block %}`` in a
- parent template.
- * If you need to get the content of the block from the parent template,
- the ``{{ block.super }}`` variable will do the trick. 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.
- * By using the same template name as you are inheriting from,
- :ttag:`{% extends %}<extends>` can be used to inherit a template at the same
- time as overriding it. Combined with ``{{ block.super }}``, this can be a
- powerful way to make small customizations. See
- :ref:`extending_an_overridden_template` in the *Overriding templates* How-to
- for a full example.
- * Variables created outside of a :ttag:`{% block %}<block>` using the template
- tag ``as`` syntax can't be used inside the block. For example, this template
- doesn't render anything:
- .. code-block:: html+django
- {% translate "Title" as title %}
- {% block content %}{{ title }}{% endblock %}
- * For extra readability, you can optionally give a *name* to your
- ``{% endblock %}`` tag. For example:
- .. code-block:: html+django
- {% block content %}
- ...
- {% endblock content %}
- In larger templates, this technique helps you see which ``{% block %}``
- tags are being closed.
- * :ttag:`{% block %}<block>` tags are evaluated first. That's why the content
- of a block is always overridden, regardless of the truthiness of surrounding
- tags. For example, this template will *always* override the content of the
- ``title`` block:
- .. code-block:: html+django
- {% if change_title %}
- {% block title %}Hello!{% endblock title %}
- {% endif %}
- Finally, note that you can't define multiple :ttag:`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 :ttag:`block` tags in a template, that template's parent
- wouldn't know which one of the blocks' content to use.
- .. _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
- <script>alert('hello')</script>
- With this name value, the template would be rendered as:
- .. code-block:: html+django
- 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?
- .. code-block:: html
- <b>username
- That would result in a rendered template like this:
- .. code-block:: html+django
- Hello, <b>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 ``'<b>'``,
- the output will be:
- .. code-block:: html+django
- This will be escaped: <b>
- This will not be escaped: <b>
- 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 %}
- <h1>{% block title %}{% endblock %}</h1>
- {% 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 ``<b>Hello!</b>``:
- .. code-block:: html+django
- <h1>This & that</h1>
- <b>Hello!</b>
- 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"<topics-db-queries-related>` 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:
- .. code-block:: html+django
- {% for comment in task.comment_set.all %}
- {{ comment }}
- {% endfor %}
- Similarly, :doc:`QuerySets</ref/models/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:
- .. code-block:: html+django
- {{ task.comment_set.all.count }}
- You can also access methods you've explicitly defined on your own models:
- .. code-block:: python
- :caption: ``models.py``
- class Task(models.Model):
- def foo(self):
- return "bar"
- .. code-block:: html+django
- :caption: ``template.html``
- {{ 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.
- .. _loading-custom-template-libraries:
- Custom tag and filter libraries
- ===============================
- Certain applications provide custom tag and filter libraries. To access them in
- a template, ensure the application is in :setting:`INSTALLED_APPS` (we'd add
- ``'django.contrib.humanize'`` for this example), and then use the :ttag:`load`
- tag in a template:
- .. code-block:: html+django
- {% load humanize %}
- {{ 45000|intcomma }}
- In the above, the :ttag:`load` tag loads the ``humanize`` tag library, which then
- makes the ``intcomma`` filter available for use. If you've enabled
- :mod:`django.contrib.admindocs`, you can consult the documentation area in your
- admin to find the list of custom libraries in your installation.
- The :ttag:`load` tag can take multiple library names, separated by spaces.
- Example:
- .. code-block:: html+django
- {% load humanize i18n %}
- See :doc:`/howto/custom-template-tags` for information on writing your own custom
- template libraries.
- Custom libraries and template inheritance
- -----------------------------------------
- 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.
- .. seealso::
- :doc:`The Templates Reference </ref/templates/index>`
- Covers built-in tags, built-in filters, using an alternative template
- language, and more.
|