如何编写一个自定义的模板后端
自定义后端
以下是如何实现一个在另一个模板系统中使用的自定义后端。一个模板后端是继承自后端基本类 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引擎,剖析显示如下:
自定义引擎可以通过在抛出 TemplateDoesNotExist 异常时传递 backend
和 tried
参数来填充后处理。使用后处理的后端 应指定模板对象上的来源。
上下文信息
当模板解析或渲染时发生错误,Django会显示错误所在的行。举个例子:
在解析或渲染异常中配置了 template_debug
属性的自定义引擎会显示这条信息。这个属性是一个有以下值的类 dict:
'name'
:发生异常的模板名称'message'
: 异常信息。'source_lines'
: 异常发生的行及其前后内容。这是为了上下文,所以它不应该超过二十行。'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和第3方集成
Django templates have an Origin object available through the template.origin
attribute. This enables debug information to be displayed in the template postmortem, as well as in 3rd-party libraries, like the Django Debug Toolbar.
自定义引擎可以通过创建有以下特定属性的对象来提供自身的 template.origin
信息。
'name'
: 模板的完整路径。'template_name'
: 通过模板加载方法打开的模板的相对路径。'loader_name'
: 一个可选的以字符串形式指定用来加载模板的文件系统类或函数, e.g.django.template.loaders.filesystem.Loader
.