如何實作自訂範本後端

自訂後端

以下說明如何實作自訂範本後端,以便使用其他範本系統。範本後端是一個繼承 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 引數來填入事後分析。使用事後分析的後端應在範本物件上指定 origin

上下文行資訊

如果範本剖析或轉譯期間發生錯誤,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,
}

Origin API 和第三方整合

Django 範本透過 template.origin 屬性提供 Origin 物件。這使除錯資訊可以顯示在範本事後分析中,以及在第三方程式庫中,例如 Django Debug Toolbar

自訂引擎可以透過建立指定以下屬性的物件來提供其自己的 template.origin 資訊

  • 'name':範本的完整路徑。

  • 'template_name':範本的相對路徑,如傳遞到範本載入方法中的路徑。

  • 'loader_name':一個可選字串,用於識別用於載入範本的函數或類別,例如 django.template.loaders.filesystem.Loader

回到頂端