如何实现自定义模板后端

自定义后端

以下是实现自定义模板后端以使用其他模板系统的方法。模板后端是一个继承自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 调试页面包含挂钩,可在出现模板错误时提供详细信息。自定义模板引擎可以使用这些挂钩来增强显示给用户的回溯信息。以下挂钩可用

模板事后分析

当引发TemplateDoesNotExist时,会出现事后分析。它列出了在尝试查找给定模板时使用的模板引擎和加载器。例如,如果配置了两个 Django 引擎,则事后分析将如下所示:

../../_images/postmortem.png

自定义引擎可以通过在引发TemplateDoesNotExist时传递backendtried参数来填充事后分析。使用事后分析的后端应该在模板对象上指定一个源

上下文行信息

如果在模板解析或渲染期间发生错误,Django 可以显示发生错误的行。例如:

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

自定义引擎可以通过在解析和渲染期间引发的异常上设置template_debug属性来填充此信息。此属性是一个具有以下值的dict

  • 'name':发生异常的模板的名称。

  • 'message':异常消息。

  • 'source_lines':异常发生前、后和包括异常发生行的行。这是为了上下文,因此它不应该包含超过 20 行左右。

  • 'line':发生异常的行号。

  • '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属性访问。这使得可以在模板事后分析以及第三方库(如Django Debug Toolbar)中显示调试信息。

自定义引擎可以通过创建一个指定以下属性的对象来提供自己的template.origin信息:

  • 'name':模板的完整路径。

  • 'template_name':传递到模板加载方法中的模板的相对路径。

  • 'loader_name':一个可选字符串,用于标识用于加载模板的函数或类,例如django.template.loaders.filesystem.Loader

返回顶部