소스 검색

Moved doc on the DTL's syntax to the ref/ section.

This makes room for a more general introduction about templating.

Updated some links to point to the new location, but kept those that
didn't talk specifically about the DTL.
Aymeric Augustin 10 년 전
부모
커밋
6c392bb2c0

+ 4 - 1
docs/index.txt

@@ -145,8 +145,11 @@ The template layer provides a designer-friendly syntax for rendering the
 information to be presented to the user. Learn how this syntax can be used by
 designers and how it can be extended by programmers:
 
+* **The basics:**
+  :doc:`Overview <topics/templates>`
+
 * **For designers:**
-  :doc:`Syntax overview <topics/templates>` |
+  :doc:`Language overview <ref/templates/language>` |
   :doc:`Built-in tags and filters <ref/templates/builtins>` |
   :doc:`Web design helpers <ref/contrib/webdesign>` |
   :doc:`Humanization <ref/contrib/humanize>`

+ 1 - 1
docs/ref/contrib/syndication.txt

@@ -118,7 +118,7 @@ into those elements.
   both.
 
   If you want to do any special formatting for either the title or
-  description, :doc:`Django templates </topics/templates>` can be used
+  description, :doc:`Django templates </ref/templates/language>` can be used
   instead. Their paths can be specified with the ``title_template`` and
   ``description_template`` attributes on the
   :class:`~django.contrib.syndication.views.Feed` class. The templates are

+ 1 - 1
docs/ref/settings.txt

@@ -2449,7 +2449,7 @@ List of locations of the template source files searched by
 
 Note that these paths should use Unix-style forward slashes, even on Windows.
 
-See :doc:`/topics/templates`.
+See :doc:`/ref/templates/language`.
 
 .. setting:: TEMPLATE_LOADERS
 

+ 1 - 1
docs/ref/templates/api.txt

@@ -7,7 +7,7 @@ The Django template language: For Python programmers
 
 This document explains the Django template system from a technical
 perspective -- how it works and how to extend it. If you're just looking for
-reference on the language syntax, see :doc:`/topics/templates`.
+reference on the language syntax, see :doc:`/ref/templates/language`.
 
 If you're looking to use the Django template system as part of another
 application -- i.e., without the rest of the framework -- make sure to read

+ 1 - 0
docs/ref/templates/index.txt

@@ -11,6 +11,7 @@ material, see :doc:`/topics/templates` topic guide.
 .. toctree::
    :maxdepth: 2
 
+   language
    builtins
    api
 

+ 704 - 0
docs/ref/templates/language.txt

@@ -0,0 +1,704 @@
+============================
+The Django template language
+============================
+
+.. admonition:: About this document
+
+    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: http://www.smarty.net/
+.. _Jinja2: http://jinja.pocoo.org/
+
+Templates
+=========
+
+.. highlightlang:: html+django
+
+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.
+
+.. 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. 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
+=========
+
+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.
+
+.. 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``::
+
+        {% for k, v in defaultdict.iteritems %}
+            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 ``.iteritems()``
+    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.
+
+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::
+
+        {{ 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::
+
+        {{ 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::
+
+        {{ 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``::
+
+        <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::
+
+        {% 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::
+
+        {% 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'``::
+
+    {# greeting #}hello
+
+A comment can contain any template code, invalid or not. 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 :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.
+
+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 :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::
+
+    {% 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::
+
+    <!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 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 :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.
+
+* For extra readability, you can optionally give a *name* to your
+  ``{% endblock %}`` tag. For example::
+
+      {% block content %}
+      ...
+      {% endblock content %}
+
+  In larger templates, this technique helps you see which ``{% block %}``
+  tags are being closed.
+
+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::
+
+    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::
+
+    <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?
+
+.. code-block:: html
+
+    <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. 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 ``&lt;``
+* ``>`` is converted to ``&gt;``
+* ``'`` (single quote) is converted to ``&#39;``
+* ``"`` (double quote) is converted to ``&quot;``
+* ``&`` is converted to ``&amp;``
+
+Again, we stress that this behavior is on by default. If you're using Django's
+template system, you're protected.
+
+.. _Cross Site Scripting: http://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::
+
+    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: &lt;b&gt;
+    This will not be escaped: <b>
+
+For template blocks
+~~~~~~~~~~~~~~~~~~~
+
+To control auto-escaping for a template, wrap the template (or just a
+particular section of the template) in the :ttag:`autoescape` tag, like so::
+
+    {% 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::
+
+    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:
+
+.. snippet::
+    :filename: base.html
+
+    {% autoescape off %}
+    <h1>{% block title %}{% endblock %}</h1>
+    {% block content %}
+    {% endblock %}
+    {% endautoescape %}
+
+.. snippet::
+    :filename: child.html
+
+    {% extends "base.html" %}
+    {% block title %}This &amp; 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 &amp; 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::
+
+    {{ 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 ::
+
+    {{ data|default:"3 &lt; 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.
+
+.. _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::
+
+    {% 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::
+
+    {{ task.comment_set.all.count }}
+
+And of course you can easily access methods you've explicitly defined on your
+own models:
+
+.. snippet::
+    :filename: models.py
+
+    class Task(models.Model):
+        def foo(self):
+            return "bar"
+
+.. snippet::
+    :filename: 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::
+
+    {% 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::
+
+    {% 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.

+ 1 - 1
docs/topics/i18n/translation.txt

@@ -529,7 +529,7 @@ Internationalization: in template code
 
 .. highlightlang:: html+django
 
-Translations in :doc:`Django templates </topics/templates>` uses two template
+Translations in :doc:`Django templates </ref/templates/language>` uses two template
 tags and a slightly different syntax than in Python code. To give your template
 access to these tags, put ``{% load i18n %}`` toward the top of your template.
 As with all template tags, this tag needs to be loaded in all templates which

+ 1 - 704
docs/topics/templates.txt

@@ -1,704 +1 @@
-============================
-The Django template language
-============================
-
-.. admonition:: About this document
-
-    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: http://www.smarty.net/
-.. _Jinja2: http://jinja.pocoo.org/
-
-Templates
-=========
-
-.. highlightlang:: html+django
-
-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.
-
-.. 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. 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
-=========
-
-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.
-
-.. 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``::
-
-        {% for k, v in defaultdict.iteritems %}
-            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 ``.iteritems()``
-    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.
-
-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::
-
-        {{ 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::
-
-        {{ 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::
-
-        {{ 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``::
-
-        <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::
-
-        {% 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::
-
-        {% 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'``::
-
-    {# greeting #}hello
-
-A comment can contain any template code, invalid or not. 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 :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.
-
-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 :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::
-
-    {% 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::
-
-    <!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 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 :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.
-
-* For extra readability, you can optionally give a *name* to your
-  ``{% endblock %}`` tag. For example::
-
-      {% block content %}
-      ...
-      {% endblock content %}
-
-  In larger templates, this technique helps you see which ``{% block %}``
-  tags are being closed.
-
-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::
-
-    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::
-
-    <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?
-
-.. code-block:: html
-
-    <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. 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 ``&lt;``
-* ``>`` is converted to ``&gt;``
-* ``'`` (single quote) is converted to ``&#39;``
-* ``"`` (double quote) is converted to ``&quot;``
-* ``&`` is converted to ``&amp;``
-
-Again, we stress that this behavior is on by default. If you're using Django's
-template system, you're protected.
-
-.. _Cross Site Scripting: http://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::
-
-    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: &lt;b&gt;
-    This will not be escaped: <b>
-
-For template blocks
-~~~~~~~~~~~~~~~~~~~
-
-To control auto-escaping for a template, wrap the template (or just a
-particular section of the template) in the :ttag:`autoescape` tag, like so::
-
-    {% 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::
-
-    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:
-
-.. snippet::
-    :filename: base.html
-
-    {% autoescape off %}
-    <h1>{% block title %}{% endblock %}</h1>
-    {% block content %}
-    {% endblock %}
-    {% endautoescape %}
-
-.. snippet::
-    :filename: child.html
-
-    {% extends "base.html" %}
-    {% block title %}This &amp; 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 &amp; 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::
-
-    {{ 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 ::
-
-    {{ data|default:"3 &lt; 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.
-
-.. _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::
-
-    {% 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::
-
-    {{ task.comment_set.all.count }}
-
-And of course you can easily access methods you've explicitly defined on your
-own models:
-
-.. snippet::
-    :filename: models.py
-
-    class Task(models.Model):
-        def foo(self):
-            return "bar"
-
-.. snippet::
-    :filename: 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::
-
-    {% 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::
-
-    {% 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.
+TODO - explain multiple template engines and the django template language