mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #25712 -- Reorganized templates docs.
This commit is contained in:
parent
f121621073
commit
bb13711451
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
173
docs/howto/custom-template-backend.txt
Normal file
173
docs/howto/custom-template-backend.txt
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
=======================
|
||||||
|
Custom template backend
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Custom backends
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Here's how to implement a custom template backend in order to use another
|
||||||
|
template system. A template backend is a class that inherits
|
||||||
|
``django.template.backends.base.BaseEngine``. It must implement
|
||||||
|
``get_template()`` and optionally ``from_string()``. Here's an example for a
|
||||||
|
fictional ``foobar`` template library::
|
||||||
|
|
||||||
|
from django.template import TemplateDoesNotExist, TemplateSyntaxError
|
||||||
|
from django.template.backends.base import BaseEngine
|
||||||
|
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy
|
||||||
|
|
||||||
|
import foobar
|
||||||
|
|
||||||
|
|
||||||
|
class FooBar(BaseEngine):
|
||||||
|
|
||||||
|
# Name of the subdirectory containing the templates for this engine
|
||||||
|
# inside an installed application.
|
||||||
|
app_dirname = 'foobar'
|
||||||
|
|
||||||
|
def __init__(self, params):
|
||||||
|
params = params.copy()
|
||||||
|
options = params.pop('OPTIONS').copy()
|
||||||
|
super().__init__(params)
|
||||||
|
|
||||||
|
self.engine = foobar.Engine(**options)
|
||||||
|
|
||||||
|
def from_string(self, template_code):
|
||||||
|
try:
|
||||||
|
return Template(self.engine.from_string(template_code))
|
||||||
|
except foobar.TemplateCompilationFailed as exc:
|
||||||
|
raise TemplateSyntaxError(exc.args)
|
||||||
|
|
||||||
|
def get_template(self, template_name):
|
||||||
|
try:
|
||||||
|
return Template(self.engine.get_template(template_name))
|
||||||
|
except foobar.TemplateNotFound as exc:
|
||||||
|
raise TemplateDoesNotExist(exc.args, backend=self)
|
||||||
|
except foobar.TemplateCompilationFailed as exc:
|
||||||
|
raise TemplateSyntaxError(exc.args)
|
||||||
|
|
||||||
|
|
||||||
|
class Template:
|
||||||
|
|
||||||
|
def __init__(self, template):
|
||||||
|
self.template = template
|
||||||
|
|
||||||
|
def render(self, context=None, request=None):
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
if request is not None:
|
||||||
|
context['request'] = request
|
||||||
|
context['csrf_input'] = csrf_input_lazy(request)
|
||||||
|
context['csrf_token'] = csrf_token_lazy(request)
|
||||||
|
return self.template.render(context)
|
||||||
|
|
||||||
|
See `DEP 182`_ for more information.
|
||||||
|
|
||||||
|
.. _template-debug-integration:
|
||||||
|
|
||||||
|
Debug integration for custom engines
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
The Django debug page has hooks to provide detailed information when a template
|
||||||
|
error arises. Custom template engines can use these hooks to enhance the
|
||||||
|
traceback information that appears to users. The following hooks are available:
|
||||||
|
|
||||||
|
.. _template-postmortem:
|
||||||
|
|
||||||
|
Template postmortem
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The postmortem appears when :exc:`~django.template.TemplateDoesNotExist` is
|
||||||
|
raised. It lists the template engines and loaders that were used when trying to
|
||||||
|
find a given template. For example, if two Django engines are configured, the
|
||||||
|
postmortem will appear like:
|
||||||
|
|
||||||
|
.. image:: _images/postmortem.png
|
||||||
|
|
||||||
|
Custom engines can populate the postmortem by passing the ``backend`` and
|
||||||
|
``tried`` arguments when raising :exc:`~django.template.TemplateDoesNotExist`.
|
||||||
|
Backends that use the postmortem :ref:`should specify an origin
|
||||||
|
<template-origin-api>` on the template object.
|
||||||
|
|
||||||
|
Contextual line information
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If an error happens during template parsing or rendering, Django can display
|
||||||
|
the line the error happened on. For example:
|
||||||
|
|
||||||
|
.. image:: _images/template-lines.png
|
||||||
|
|
||||||
|
Custom engines can populate this information by setting a ``template_debug``
|
||||||
|
attribute on exceptions raised during parsing and rendering. This attribute is
|
||||||
|
a :class:`dict` with the following values:
|
||||||
|
|
||||||
|
* ``'name'``: The name of the template in which the exception occurred.
|
||||||
|
|
||||||
|
* ``'message'``: The exception message.
|
||||||
|
|
||||||
|
* ``'source_lines'``: The lines before, after, and including the line the
|
||||||
|
exception occurred on. This is for context, so it shouldn't contain more than
|
||||||
|
20 lines or so.
|
||||||
|
|
||||||
|
* ``'line'``: The line number on which the exception occurred.
|
||||||
|
|
||||||
|
* ``'before'``: The content on the error line before the token that raised the
|
||||||
|
error.
|
||||||
|
|
||||||
|
* ``'during'``: The token that raised the error.
|
||||||
|
|
||||||
|
* ``'after'``: The content on the error line after the token that raised the
|
||||||
|
error.
|
||||||
|
|
||||||
|
* ``'total'``: The number of lines in ``source_lines``.
|
||||||
|
|
||||||
|
* ``'top'``: The line number where ``source_lines`` starts.
|
||||||
|
|
||||||
|
* ``'bottom'``: The line number where ``source_lines`` ends.
|
||||||
|
|
||||||
|
Given the above template error, ``template_debug`` would look like::
|
||||||
|
|
||||||
|
{
|
||||||
|
'name': '/path/to/template.html',
|
||||||
|
'message': "Invalid block tag: 'syntax'",
|
||||||
|
'source_lines': [
|
||||||
|
(1, 'some\n'),
|
||||||
|
(2, 'lines\n'),
|
||||||
|
(3, 'before\n'),
|
||||||
|
(4, 'Hello {% syntax error %} {{ world }}\n'),
|
||||||
|
(5, 'some\n'),
|
||||||
|
(6, 'lines\n'),
|
||||||
|
(7, 'after\n'),
|
||||||
|
(8, ''),
|
||||||
|
],
|
||||||
|
'line': 4,
|
||||||
|
'before': 'Hello ',
|
||||||
|
'during': '{% syntax error %}',
|
||||||
|
'after': ' {{ world }}\n',
|
||||||
|
'total': 9,
|
||||||
|
'bottom': 9,
|
||||||
|
'top': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
.. _template-origin-api:
|
||||||
|
|
||||||
|
Origin API and 3rd-party integration
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Django templates have an :class:`~django.template.base.Origin` object available
|
||||||
|
through the ``template.origin`` attribute. This enables debug information to be
|
||||||
|
displayed in the :ref:`template postmortem <template-postmortem>`, as well as
|
||||||
|
in 3rd-party libraries, like the `Django Debug Toolbar`_.
|
||||||
|
|
||||||
|
Custom engines can provide their own ``template.origin`` information by
|
||||||
|
creating an object that specifies the following attributes:
|
||||||
|
|
||||||
|
* ``'name'``: The full path to the template.
|
||||||
|
|
||||||
|
* ``'template_name'``: The relative path to the template as passed into the
|
||||||
|
template loading methods.
|
||||||
|
|
||||||
|
* ``'loader_name'``: An optional string identifying the function or class used
|
||||||
|
to load the template, e.g. ``django.template.loaders.filesystem.Loader``.
|
||||||
|
|
||||||
|
.. _DEP 182: https://github.com/django/deps/blob/master/final/0182-multiple-template-engines.rst
|
||||||
|
.. _Django Debug Toolbar: https://github.com/jazzband/django-debug-toolbar
|
@ -14,6 +14,7 @@ you quickly accomplish common tasks.
|
|||||||
custom-management-commands
|
custom-management-commands
|
||||||
custom-model-fields
|
custom-model-fields
|
||||||
custom-lookups
|
custom-lookups
|
||||||
|
custom-template-backend
|
||||||
custom-template-tags
|
custom-template-tags
|
||||||
custom-file-storage
|
custom-file-storage
|
||||||
deployment/index
|
deployment/index
|
||||||
|
@ -173,7 +173,8 @@ designers and how it can be extended by programmers:
|
|||||||
|
|
||||||
* **For programmers:**
|
* **For programmers:**
|
||||||
:doc:`Template API <ref/templates/api>` |
|
:doc:`Template API <ref/templates/api>` |
|
||||||
:doc:`Custom tags and filters <howto/custom-template-tags>`
|
:doc:`Custom tags and filters <howto/custom-template-tags>` |
|
||||||
|
:doc:`Custom template backend <howto/custom-template-backend>`
|
||||||
|
|
||||||
Forms
|
Forms
|
||||||
=====
|
=====
|
||||||
|
@ -15,7 +15,8 @@ A Django project can be configured with one or several template engines (or
|
|||||||
even zero if you don't use templates). Django ships built-in backends for its
|
even zero if you don't use templates). Django ships built-in backends for its
|
||||||
own template system, creatively called the Django template language (DTL), and
|
own template system, creatively called the Django template language (DTL), and
|
||||||
for the popular alternative Jinja2_. Backends for other template languages may
|
for the popular alternative Jinja2_. Backends for other template languages may
|
||||||
be available from third-parties.
|
be available from third-parties. You can also write your own custom backend,
|
||||||
|
see :doc:`Custom template backend </howto/custom-template-backend>`
|
||||||
|
|
||||||
Django defines a standard API for loading and rendering templates regardless
|
Django defines a standard API for loading and rendering templates regardless
|
||||||
of the backend. Loading consists of finding the template for a given identifier
|
of the backend. Loading consists of finding the template for a given identifier
|
||||||
@ -43,11 +44,183 @@ namespace.
|
|||||||
since template authors can do things like perform XSS attacks and access
|
since template authors can do things like perform XSS attacks and access
|
||||||
properties of template variables that may contain sensitive information.
|
properties of template variables that may contain sensitive information.
|
||||||
|
|
||||||
|
.. _template-language-intro:
|
||||||
|
|
||||||
|
The Django template language
|
||||||
|
============================
|
||||||
|
|
||||||
|
.. highlight:: html+django
|
||||||
|
|
||||||
|
Syntax
|
||||||
|
------
|
||||||
|
|
||||||
|
.. admonition:: About this section
|
||||||
|
|
||||||
|
This is an overview of the Django template language's syntax. For details
|
||||||
|
see the :doc:`language syntax reference </ref/templates/language>`.
|
||||||
|
|
||||||
|
A Django template is a text document or a Python string marked-up using the
|
||||||
|
Django template language. Some constructs are recognized and interpreted by the
|
||||||
|
template engine. The main ones are variables and tags.
|
||||||
|
|
||||||
|
A template is rendered with a context. Rendering replaces variables with their
|
||||||
|
values, which are looked up in the context, and executes tags. Everything else
|
||||||
|
is output as is.
|
||||||
|
|
||||||
|
The syntax of the Django template language involves four constructs.
|
||||||
|
|
||||||
|
Variables
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
A variable outputs a value from the context, which is a dict-like object
|
||||||
|
mapping keys to values.
|
||||||
|
|
||||||
|
Variables are surrounded by ``{{`` and ``}}`` like this::
|
||||||
|
|
||||||
|
My first name is {{ first_name }}. My last name is {{ last_name }}.
|
||||||
|
|
||||||
|
With a context of ``{'first_name': 'John', 'last_name': 'Doe'}``, this template
|
||||||
|
renders to::
|
||||||
|
|
||||||
|
My first name is John. My last name is Doe.
|
||||||
|
|
||||||
|
Dictionary lookup, attribute lookup and list-index lookups are implemented with
|
||||||
|
a dot notation::
|
||||||
|
|
||||||
|
{{ my_dict.key }}
|
||||||
|
{{ my_object.attribute }}
|
||||||
|
{{ my_list.0 }}
|
||||||
|
|
||||||
|
If a variable resolves to a callable, the template system will call it with no
|
||||||
|
arguments and use its result instead of the callable.
|
||||||
|
|
||||||
|
Tags
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
Tags provide arbitrary logic in the rendering process.
|
||||||
|
|
||||||
|
This definition is deliberately vague. For example, a tag can output content,
|
||||||
|
serve as a control structure e.g. an "if" statement or a "for" loop, grab
|
||||||
|
content from a database, or even enable access to other template tags.
|
||||||
|
|
||||||
|
Tags are surrounded by ``{%`` and ``%}`` like this::
|
||||||
|
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
Most tags accept arguments::
|
||||||
|
|
||||||
|
{% cycle 'odd' 'even' %}
|
||||||
|
|
||||||
|
Some tags require beginning and ending tags::
|
||||||
|
|
||||||
|
{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
|
||||||
|
|
||||||
|
A :ref:`reference of built-in tags <ref-templates-builtins-tags>` is
|
||||||
|
available as well as :ref:`instructions for writing custom tags
|
||||||
|
<howto-writing-custom-template-tags>`.
|
||||||
|
|
||||||
|
Filters
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
Filters transform the values of variables and tag arguments.
|
||||||
|
|
||||||
|
They look like this::
|
||||||
|
|
||||||
|
{{ django|title }}
|
||||||
|
|
||||||
|
With a context of ``{'django': 'the web framework for perfectionists with
|
||||||
|
deadlines'}``, this template renders to::
|
||||||
|
|
||||||
|
The Web Framework For Perfectionists With Deadlines
|
||||||
|
|
||||||
|
Some filters take an argument::
|
||||||
|
|
||||||
|
{{ my_date|date:"Y-m-d" }}
|
||||||
|
|
||||||
|
A :ref:`reference of built-in filters <ref-templates-builtins-filters>` is
|
||||||
|
available as well as :ref:`instructions for writing custom filters
|
||||||
|
<howto-writing-custom-template-filters>`.
|
||||||
|
|
||||||
|
Comments
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
Comments look like this::
|
||||||
|
|
||||||
|
{# this won't be rendered #}
|
||||||
|
|
||||||
|
A :ttag:`{% comment %} <comment>` tag provides multi-line comments.
|
||||||
|
|
||||||
|
Components
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. admonition:: About this section
|
||||||
|
|
||||||
|
This is an overview of the Django template language's APIs. For details
|
||||||
|
see the :doc:`API reference </ref/templates/api>`.
|
||||||
|
|
||||||
|
Engine
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
:class:`django.template.Engine` encapsulates an instance of the Django
|
||||||
|
template system. The main reason for instantiating an
|
||||||
|
:class:`~django.template.Engine` directly is to use the Django template
|
||||||
|
language outside of a Django project.
|
||||||
|
|
||||||
|
:class:`django.template.backends.django.DjangoTemplates` is a thin wrapper
|
||||||
|
adapting :class:`django.template.Engine` to Django's template backend API.
|
||||||
|
|
||||||
|
Template
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
|
:class:`django.template.Template` represents a compiled template. Templates are
|
||||||
|
obtained with :meth:`.Engine.get_template` or :meth:`.Engine.from_string`.
|
||||||
|
|
||||||
|
Likewise ``django.template.backends.django.Template`` is a thin wrapper
|
||||||
|
adapting :class:`django.template.Template` to the common template API.
|
||||||
|
|
||||||
|
Context
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
:class:`django.template.Context` holds some metadata in addition to the context
|
||||||
|
data. It is passed to :meth:`.Template.render` for rendering a template.
|
||||||
|
|
||||||
|
:class:`django.template.RequestContext` is a subclass of
|
||||||
|
:class:`~django.template.Context` that stores the current
|
||||||
|
:class:`~django.http.HttpRequest` and runs template context processors.
|
||||||
|
|
||||||
|
The common API doesn't have an equivalent concept. Context data is passed in a
|
||||||
|
plain :class:`dict` and the current :class:`~django.http.HttpRequest` is passed
|
||||||
|
separately if needed.
|
||||||
|
|
||||||
|
Loaders
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
Template loaders are responsible for locating templates, loading them, and
|
||||||
|
returning :class:`~django.template.Template` objects.
|
||||||
|
|
||||||
|
Django provides several :ref:`built-in template loaders <template-loaders>`
|
||||||
|
and supports :ref:`custom template loaders <custom-template-loaders>`.
|
||||||
|
|
||||||
|
Context processors
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Context processors are functions that receive the current
|
||||||
|
:class:`~django.http.HttpRequest` as an argument and return a :class:`dict` of
|
||||||
|
data to be added to the rendering context.
|
||||||
|
|
||||||
|
Their main use is to add common data shared by all templates to the context
|
||||||
|
without repeating code in every view.
|
||||||
|
|
||||||
|
Django provides many :ref:`built-in context processors <context-processors>`,
|
||||||
|
and you can implement your own additional context processors, too.
|
||||||
|
|
||||||
.. _template-engines:
|
.. _template-engines:
|
||||||
|
|
||||||
Support for template engines
|
Support for template engines
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
.. highlight:: python
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -483,348 +656,4 @@ templates, as shown in the example above. Jinja2's global namespace removes the
|
|||||||
need for template context processors. The Django template language doesn't have
|
need for template context processors. The Django template language doesn't have
|
||||||
an equivalent of Jinja2 tests.
|
an equivalent of Jinja2 tests.
|
||||||
|
|
||||||
Custom backends
|
.. _Jinja2: https://jinja.palletsprojects.com/
|
||||||
---------------
|
|
||||||
|
|
||||||
Here's how to implement a custom template backend in order to use another
|
|
||||||
template system. A template backend is a class that inherits
|
|
||||||
``django.template.backends.base.BaseEngine``. It must implement
|
|
||||||
``get_template()`` and optionally ``from_string()``. Here's an example for a
|
|
||||||
fictional ``foobar`` template library::
|
|
||||||
|
|
||||||
from django.template import TemplateDoesNotExist, TemplateSyntaxError
|
|
||||||
from django.template.backends.base import BaseEngine
|
|
||||||
from django.template.backends.utils import csrf_input_lazy, csrf_token_lazy
|
|
||||||
|
|
||||||
import foobar
|
|
||||||
|
|
||||||
|
|
||||||
class FooBar(BaseEngine):
|
|
||||||
|
|
||||||
# Name of the subdirectory containing the templates for this engine
|
|
||||||
# inside an installed application.
|
|
||||||
app_dirname = 'foobar'
|
|
||||||
|
|
||||||
def __init__(self, params):
|
|
||||||
params = params.copy()
|
|
||||||
options = params.pop('OPTIONS').copy()
|
|
||||||
super().__init__(params)
|
|
||||||
|
|
||||||
self.engine = foobar.Engine(**options)
|
|
||||||
|
|
||||||
def from_string(self, template_code):
|
|
||||||
try:
|
|
||||||
return Template(self.engine.from_string(template_code))
|
|
||||||
except foobar.TemplateCompilationFailed as exc:
|
|
||||||
raise TemplateSyntaxError(exc.args)
|
|
||||||
|
|
||||||
def get_template(self, template_name):
|
|
||||||
try:
|
|
||||||
return Template(self.engine.get_template(template_name))
|
|
||||||
except foobar.TemplateNotFound as exc:
|
|
||||||
raise TemplateDoesNotExist(exc.args, backend=self)
|
|
||||||
except foobar.TemplateCompilationFailed as exc:
|
|
||||||
raise TemplateSyntaxError(exc.args)
|
|
||||||
|
|
||||||
|
|
||||||
class Template:
|
|
||||||
|
|
||||||
def __init__(self, template):
|
|
||||||
self.template = template
|
|
||||||
|
|
||||||
def render(self, context=None, request=None):
|
|
||||||
if context is None:
|
|
||||||
context = {}
|
|
||||||
if request is not None:
|
|
||||||
context['request'] = request
|
|
||||||
context['csrf_input'] = csrf_input_lazy(request)
|
|
||||||
context['csrf_token'] = csrf_token_lazy(request)
|
|
||||||
return self.template.render(context)
|
|
||||||
|
|
||||||
See `DEP 182`_ for more information.
|
|
||||||
|
|
||||||
.. _template-debug-integration:
|
|
||||||
|
|
||||||
Debug integration for custom engines
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
The Django debug page has hooks to provide detailed information when a template
|
|
||||||
error arises. Custom template engines can use these hooks to enhance the
|
|
||||||
traceback information that appears to users. The following hooks are available:
|
|
||||||
|
|
||||||
.. _template-postmortem:
|
|
||||||
|
|
||||||
Template postmortem
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The postmortem appears when :exc:`~django.template.TemplateDoesNotExist` is
|
|
||||||
raised. It lists the template engines and loaders that were used when trying
|
|
||||||
to find a given template. For example, if two Django engines are configured,
|
|
||||||
the postmortem will appear like:
|
|
||||||
|
|
||||||
.. image:: _images/postmortem.png
|
|
||||||
|
|
||||||
Custom engines can populate the postmortem by passing the ``backend`` and
|
|
||||||
``tried`` arguments when raising :exc:`~django.template.TemplateDoesNotExist`.
|
|
||||||
Backends that use the postmortem :ref:`should specify an origin
|
|
||||||
<template-origin-api>` on the template object.
|
|
||||||
|
|
||||||
Contextual line information
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
If an error happens during template parsing or rendering, Django can display
|
|
||||||
the line the error happened on. For example:
|
|
||||||
|
|
||||||
.. image:: _images/template-lines.png
|
|
||||||
|
|
||||||
Custom engines can populate this information by setting a ``template_debug``
|
|
||||||
attribute on exceptions raised during parsing and rendering. This attribute
|
|
||||||
is a :class:`dict` with the following values:
|
|
||||||
|
|
||||||
* ``'name'``: The name of the template in which the exception occurred.
|
|
||||||
|
|
||||||
* ``'message'``: The exception message.
|
|
||||||
|
|
||||||
* ``'source_lines'``: The lines before, after, and including the line the
|
|
||||||
exception occurred on. This is for context, so it shouldn't contain more than
|
|
||||||
20 lines or so.
|
|
||||||
|
|
||||||
* ``'line'``: The line number on which the exception occurred.
|
|
||||||
|
|
||||||
* ``'before'``: The content on the error line before the token that raised the
|
|
||||||
error.
|
|
||||||
|
|
||||||
* ``'during'``: The token that raised the error.
|
|
||||||
|
|
||||||
* ``'after'``: The content on the error line after the token that raised the
|
|
||||||
error.
|
|
||||||
|
|
||||||
* ``'total'``: The number of lines in ``source_lines``.
|
|
||||||
|
|
||||||
* ``'top'``: The line number where ``source_lines`` starts.
|
|
||||||
|
|
||||||
* ``'bottom'``: The line number where ``source_lines`` ends.
|
|
||||||
|
|
||||||
Given the above template error, ``template_debug`` would look like::
|
|
||||||
|
|
||||||
{
|
|
||||||
'name': '/path/to/template.html',
|
|
||||||
'message': "Invalid block tag: 'syntax'",
|
|
||||||
'source_lines': [
|
|
||||||
(1, 'some\n'),
|
|
||||||
(2, 'lines\n'),
|
|
||||||
(3, 'before\n'),
|
|
||||||
(4, 'Hello {% syntax error %} {{ world }}\n'),
|
|
||||||
(5, 'some\n'),
|
|
||||||
(6, 'lines\n'),
|
|
||||||
(7, 'after\n'),
|
|
||||||
(8, ''),
|
|
||||||
],
|
|
||||||
'line': 4,
|
|
||||||
'before': 'Hello ',
|
|
||||||
'during': '{% syntax error %}',
|
|
||||||
'after': ' {{ world }}\n',
|
|
||||||
'total': 9,
|
|
||||||
'bottom': 9,
|
|
||||||
'top': 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
.. _template-origin-api:
|
|
||||||
|
|
||||||
Origin API and 3rd-party integration
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Django templates have an :class:`~django.template.base.Origin` object available
|
|
||||||
through the ``template.origin`` attribute. This enables debug information to be
|
|
||||||
displayed in the :ref:`template postmortem <template-postmortem>`, as well as
|
|
||||||
in 3rd-party libraries, like the `Django Debug Toolbar`_.
|
|
||||||
|
|
||||||
Custom engines can provide their own ``template.origin`` information by
|
|
||||||
creating an object that specifies the following attributes:
|
|
||||||
|
|
||||||
* ``'name'``: The full path to the template.
|
|
||||||
|
|
||||||
* ``'template_name'``: The relative path to the template as passed into the
|
|
||||||
template loading methods.
|
|
||||||
|
|
||||||
* ``'loader_name'``: An optional string identifying the function or class used
|
|
||||||
to load the template, e.g. ``django.template.loaders.filesystem.Loader``.
|
|
||||||
|
|
||||||
.. currentmodule:: django.template
|
|
||||||
|
|
||||||
.. _template-language-intro:
|
|
||||||
|
|
||||||
The Django template language
|
|
||||||
============================
|
|
||||||
|
|
||||||
.. highlight:: html+django
|
|
||||||
|
|
||||||
Syntax
|
|
||||||
------
|
|
||||||
|
|
||||||
.. admonition:: About this section
|
|
||||||
|
|
||||||
This is an overview of the Django template language's syntax. For details
|
|
||||||
see the :doc:`language syntax reference </ref/templates/language>`.
|
|
||||||
|
|
||||||
A Django template is a text document or a Python string marked-up using the
|
|
||||||
Django template language. Some constructs are recognized and interpreted by the
|
|
||||||
template engine. The main ones are variables and tags.
|
|
||||||
|
|
||||||
A template is rendered with a context. Rendering replaces variables with their
|
|
||||||
values, which are looked up in the context, and executes tags. Everything else
|
|
||||||
is output as is.
|
|
||||||
|
|
||||||
The syntax of the Django template language involves four constructs.
|
|
||||||
|
|
||||||
Variables
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
A variable outputs a value from the context, which is a dict-like object
|
|
||||||
mapping keys to values.
|
|
||||||
|
|
||||||
Variables are surrounded by ``{{`` and ``}}`` like this::
|
|
||||||
|
|
||||||
My first name is {{ first_name }}. My last name is {{ last_name }}.
|
|
||||||
|
|
||||||
With a context of ``{'first_name': 'John', 'last_name': 'Doe'}``, this
|
|
||||||
template renders to::
|
|
||||||
|
|
||||||
My first name is John. My last name is Doe.
|
|
||||||
|
|
||||||
Dictionary lookup, attribute lookup and list-index lookups are implemented
|
|
||||||
with a dot notation::
|
|
||||||
|
|
||||||
{{ my_dict.key }}
|
|
||||||
{{ my_object.attribute }}
|
|
||||||
{{ my_list.0 }}
|
|
||||||
|
|
||||||
If a variable resolves to a callable, the template system will call it with no
|
|
||||||
arguments and use its result instead of the callable.
|
|
||||||
|
|
||||||
Tags
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
Tags provide arbitrary logic in the rendering process.
|
|
||||||
|
|
||||||
This definition is deliberately vague. For example, a tag can output content,
|
|
||||||
serve as a control structure e.g. an "if" statement or a "for" loop, grab
|
|
||||||
content from a database, or even enable access to other template tags.
|
|
||||||
|
|
||||||
Tags are surrounded by ``{%`` and ``%}`` like this::
|
|
||||||
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
Most tags accept arguments::
|
|
||||||
|
|
||||||
{% cycle 'odd' 'even' %}
|
|
||||||
|
|
||||||
Some tags require beginning and ending tags::
|
|
||||||
|
|
||||||
{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
|
|
||||||
|
|
||||||
A :ref:`reference of built-in tags <ref-templates-builtins-tags>` is
|
|
||||||
available as well as :ref:`instructions for writing custom tags
|
|
||||||
<howto-writing-custom-template-tags>`.
|
|
||||||
|
|
||||||
Filters
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
Filters transform the values of variables and tag arguments.
|
|
||||||
|
|
||||||
They look like this::
|
|
||||||
|
|
||||||
{{ django|title }}
|
|
||||||
|
|
||||||
With a context of ``{'django': 'the web framework for perfectionists with
|
|
||||||
deadlines'}``, this template renders to::
|
|
||||||
|
|
||||||
The Web Framework For Perfectionists With Deadlines
|
|
||||||
|
|
||||||
Some filters take an argument::
|
|
||||||
|
|
||||||
{{ my_date|date:"Y-m-d" }}
|
|
||||||
|
|
||||||
A :ref:`reference of built-in filters <ref-templates-builtins-filters>` is
|
|
||||||
available as well as :ref:`instructions for writing custom filters
|
|
||||||
<howto-writing-custom-template-filters>`.
|
|
||||||
|
|
||||||
Comments
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
Comments look like this::
|
|
||||||
|
|
||||||
{# this won't be rendered #}
|
|
||||||
|
|
||||||
A :ttag:`{% comment %} <comment>` tag provides multi-line comments.
|
|
||||||
|
|
||||||
Components
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. admonition:: About this section
|
|
||||||
|
|
||||||
This is an overview of the Django template language's APIs. For details
|
|
||||||
see the :doc:`API reference </ref/templates/api>`.
|
|
||||||
|
|
||||||
Engine
|
|
||||||
~~~~~~
|
|
||||||
|
|
||||||
:class:`django.template.Engine` encapsulates an instance of the Django
|
|
||||||
template system. The main reason for instantiating an
|
|
||||||
:class:`~django.template.Engine` directly is to use the Django template
|
|
||||||
language outside of a Django project.
|
|
||||||
|
|
||||||
:class:`django.template.backends.django.DjangoTemplates` is a thin wrapper
|
|
||||||
adapting :class:`django.template.Engine` to Django's template backend API.
|
|
||||||
|
|
||||||
Template
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
:class:`django.template.Template` represents a compiled template.
|
|
||||||
Templates are obtained with :meth:`Engine.get_template()
|
|
||||||
<django.template.Engine.get_template>` or :meth:`Engine.from_string()
|
|
||||||
<django.template.Engine.from_string>`
|
|
||||||
|
|
||||||
Likewise ``django.template.backends.django.Template`` is a thin wrapper
|
|
||||||
adapting :class:`django.template.Template` to the common template API.
|
|
||||||
|
|
||||||
Context
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
:class:`django.template.Context` holds some metadata in addition to the
|
|
||||||
context data. It is passed to :meth:`Template.render()
|
|
||||||
<django.template.Template.render>` for rendering a template.
|
|
||||||
|
|
||||||
:class:`django.template.RequestContext` is a subclass of
|
|
||||||
:class:`~django.template.Context` that stores the current
|
|
||||||
:class:`~django.http.HttpRequest` and runs template context processors.
|
|
||||||
|
|
||||||
The common API doesn't have an equivalent concept. Context data is passed in a
|
|
||||||
plain :class:`dict` and the current :class:`~django.http.HttpRequest` is passed
|
|
||||||
separately if needed.
|
|
||||||
|
|
||||||
Loaders
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
Template loaders are responsible for locating templates, loading them, and
|
|
||||||
returning :class:`~django.template.Template` objects.
|
|
||||||
|
|
||||||
Django provides several :ref:`built-in template loaders <template-loaders>`
|
|
||||||
and supports :ref:`custom template loaders <custom-template-loaders>`.
|
|
||||||
|
|
||||||
Context processors
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Context processors are functions that receive the current
|
|
||||||
:class:`~django.http.HttpRequest` as an argument and return a :class:`dict` of
|
|
||||||
data to be added to the rendering context.
|
|
||||||
|
|
||||||
Their main use is to add common data shared by all templates to the context
|
|
||||||
without repeating code in every view.
|
|
||||||
|
|
||||||
Django provides many :ref:`built-in context processors <context-processors>`,
|
|
||||||
and you can implement your own additional context processors, too.
|
|
||||||
|
|
||||||
.. _Jinja2: http://jinja.pocoo.org/
|
|
||||||
.. _DEP 182: https://github.com/django/deps/blob/master/final/0182-multiple-template-engines.rst
|
|
||||||
.. _Django Debug Toolbar: https://github.com/jazzband/django-debug-toolbar
|
|
||||||
|
Loading…
Reference in New Issue
Block a user