|
@@ -152,11 +152,32 @@ The ``django.template.loader`` module defines two functions to load templates.
|
|
|
If loading a template fails, the following two exceptions, defined in
|
|
|
``django.template``, may be raised:
|
|
|
|
|
|
-.. exception:: TemplateDoesNotExist
|
|
|
+.. exception:: TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)
|
|
|
|
|
|
- This exception is raised when a template cannot be found.
|
|
|
+ This exception is raised when a template cannot be found. It accepts the
|
|
|
+ following optional arguments for populating the :ref:`template postmortem
|
|
|
+ <template-postmortem>` on the debug page:
|
|
|
|
|
|
-.. exception:: TemplateSyntaxError
|
|
|
+ ``backend``
|
|
|
+ The template backend instance from which the exception originated.
|
|
|
+
|
|
|
+ ``tried``
|
|
|
+ A list of sources that were tried when finding the template. This is
|
|
|
+ formatted as a list of tuples containing ``(origin, status)``, where
|
|
|
+ ``origin`` is an :ref:`origin-like <template-origin-api>` object and
|
|
|
+ ``status`` is a string with the reason the template wasn't found.
|
|
|
+
|
|
|
+ ``chain``
|
|
|
+ A list of intermediate :exc:`~django.template.TemplateDoesNotExist`
|
|
|
+ exceptions raised when trying to load a template. This is used by
|
|
|
+ functions, such as :func:`~django.template.loader.get_template`, that
|
|
|
+ try to load a given template from multiple engines.
|
|
|
+
|
|
|
+ .. versionadded:: 1.9
|
|
|
+
|
|
|
+ The ``backend``, ``tried``, and ``chain`` arguments were added.
|
|
|
+
|
|
|
+.. exception:: TemplateSyntaxError(msg)
|
|
|
|
|
|
This exception is raised when a template was found but contains errors.
|
|
|
|
|
@@ -478,7 +499,6 @@ fictional ``foobar`` template library::
|
|
|
|
|
|
self.engine = foobar.Engine(**options)
|
|
|
|
|
|
-
|
|
|
def from_string(self, template_code):
|
|
|
try:
|
|
|
return Template(self.engine.from_string(template_code))
|
|
@@ -489,7 +509,7 @@ fictional ``foobar`` template library::
|
|
|
try:
|
|
|
return Template(self.engine.get_template(template_name))
|
|
|
except foobar.TemplateNotFound as exc:
|
|
|
- raise TemplateDoesNotExist(exc.args)
|
|
|
+ raise TemplateDoesNotExist(exc.args, backend=self)
|
|
|
except foobar.TemplateCompilationFailed as exc:
|
|
|
raise TemplateSyntaxError(exc.args)
|
|
|
|
|
@@ -510,6 +530,117 @@ fictional ``foobar`` template library::
|
|
|
|
|
|
See `DEP 182`_ for more information.
|
|
|
|
|
|
+.. _template-debug-integration:
|
|
|
+
|
|
|
+Debug integration for custom engines
|
|
|
+------------------------------------
|
|
|
+
|
|
|
+.. versionadded:: 1.9
|
|
|
+
|
|
|
+ Debug page integration for non-Django template engines was added.
|
|
|
+
|
|
|
+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
|
|
|
+ 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:
|
|
@@ -687,3 +818,4 @@ Implementing a custom context processor is as simple as defining a function.
|
|
|
|
|
|
.. _Jinja2: http://jinja.pocoo.org/
|
|
|
.. _DEP 182: https://github.com/django/deps/blob/master/accepted/0182-multiple-template-engines.rst
|
|
|
+.. _Django Debug Toolbar: https://github.com/django-debug-toolbar/django-debug-toolbar
|