Бэкэнд с пользовательскими шаблонами

Пользовательские бэкенды

Вот как реализовать собственный шаблонный бэкэнд, чтобы использовать другую систему шаблонов. Бэкэнд шаблона - это класс, унаследованный от django.template.backends.base.BaseEngine. Он должен реализовывать get_template() и, необязательно, from_string(). Вот пример вымышленной библиотеки шаблонов foobar:

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)

Смотрите DEP 182 для получения дополнительной информации.

Интеграция отладки для пользовательских движков

На странице отладки Django есть перехватчики для предоставления подробной информации при возникновении ошибки шаблона. Пользовательские механизмы шаблонов могут использовать эти перехватчики для улучшения информации трассировки, отображаемой для пользователей. Доступны следующие хуки:

Шаблон postmortem

Постмортем появляется, когда вызывается TemplateDoesNotExist. В нем перечислены механизмы и загрузчики шаблонов, которые использовались при попытке найти данный шаблон. Например, если настроены два движка Django, постмортем будет выглядеть так:

../../_images/postmortem.png

Пользовательские движки могут заполнять постмортем, передавая аргументы backend и tried при вызове TemplateDoesNotExist. Бэкэнды, использующие postmortem должны указывать источник в объекте шаблона.

Информация о контекстной строке

Если ошибка возникает во время синтаксического анализа или рендеринга шаблона, Django может отобразить строку, в которой произошла ошибка. Например:

../../_images/template-lines.png

Пользовательские механизмы могут заполнить эту информацию, установив атрибут template_debug для исключений, возникающих во время синтаксического анализа и рендеринга. Этот атрибут представляет собой dict со следующими значениями:

  • 'name': имя шаблона, в котором произошло исключение.
  • 'message': сообщение об исключении.
  • 'source_lines': строки до, после и включая строку, в которой произошло исключение. Это для контекста, поэтому он не должен содержать более 20 строк или около того.
  • 'строка': номер строки, в которой произошло исключение.
  • 'before': содержимое строки ошибки перед токеном, вызвавшим ошибку.
  • 'during': токен, вызвавший ошибку.
  • 'after': содержимое строки ошибки после токена, вызвавшего ошибку.
  • 'total': количество строк в source_lines.
  • 'top': номер строки, с которой начинается source_lines.
  • 'bottom': номер строки, на которой заканчивается source_lines.

Учитывая указанную выше ошибку шаблона, template_debug будет выглядеть так:

{
    '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,
}

API и сторонняя интеграция

В шаблонах Django есть объект Origin, доступный через атрибут template.origin. Это позволяет отображать отладочную информацию в template postmortem, а также в сторонних библиотеках, таких как Django Debug Toolbar.

Пользовательские движки могут предоставить свою собственную информацию template.origin, создав объект, который задает следующие атрибуты:

  • 'name': полный путь к шаблону.
  • 'template_name': Относительный путь к шаблону, передаваемый в методы загрузки шаблона.
  • 'loader_name': необязательная строка, определяющая функцию или класс, используемый для загрузки шаблона, например django.template.loaders.filesystem.Loader.
Вернуться на верх