カスタムテンプレートバックエンド—Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/3.2.x/howto/custom-template-backend
移動先:案内検索

カスタムテンプレートバックエンド

カスタムバックエンド

別のテンプレートシステムを使用するためにカスタムテンプレートバックエンドを実装する方法は次のとおりです。 テンプレートバックエンドは、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 が発生すると、事後分析が表示されます。 特定のテンプレートを検索するときに使用されたテンプレートエンジンとローダーが一覧表示されます。 たとえば、2つのDjangoエンジンが構成されている場合、事後分析は次のように表示されます。

../_images/postmortem.png カスタムエンジンは、 TemplateDoesNotExist を発生させるときに、backendおよびtried引数を渡すことにより、事後分析を行うことができます。 事後分析を使用するバックエンドは、テンプレートオブジェクトの起点を指定する必要があります。


コンテキストライン情報

テンプレートの解析またはレンダリング中にエラーが発生した場合、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,
}

OriginAPIとサードパーティの統合

Djangoテンプレートには、template.origin属性を介して使用できる Origin オブジェクトがあります。 これにより、デバッグ情報をテンプレートの事後分析や、 Djangoデバッグツールバーなどのサードパーティライブラリに表示できます。

カスタムエンジンは、次の属性を指定するオブジェクトを作成することにより、独自のtemplate.origin情報を提供できます。

  • 'name':テンプレートへのフルパス。
  • 'template_name':テンプレートの読み込みメソッドに渡されるテンプレートへの相対パス。
  • 'loader_name':テンプレートのロードに使用される関数またはクラスを識別するオプションの文字列。 django.template.loaders.filesystem.Loader