Djangoで文字列をテンプレートとして使う

Djangoでテンプレートエンジンを使う場合、テンプレートはファイルとして用意する場合が多いですが、文字列を入力とすることもできます。

The Django template language: for Python programmers | Django documentation | Django

試したバージョンは、Python3.10, Django4.2.2

Templateクラスの使用例

django.template.Templatedjango.template.Context を利用します。

Templateクラスは抽象化されたテンプレート、Contextクラスはテンプレートに渡す変数などを格納した辞書に似たインターフェースのコンテキストです。

>>> from django.template import Template, Context
>>> template = Template("今日の日付: {% now 'Y-m-d' %}\nコンテキストで渡した値: {{ spam }}")
>>> context = Context({"spam": "egg"})
>>> template.render(context)
'今日の日付: 2023-07-02\nコンテキストで渡した値: egg'

template.render() の引数には Context クラスのインスタンスを指定する必要があります。dictを渡すとエラーになります。 Context クラスはコンストラクタに辞書を指定できます。

>>> template.render({"spam": "egg"})
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/vagrant/tmp/venv/lib/python3.10/site-packages/django/template/base.py", line 171, in render
    with context.render_context.push_state(self):
AttributeError: 'dict' object has no attribute 'render_context'

この template インスタンスのクラスは、 django.template.base.Template となっています。

>>> type(template)
<class 'django.template.base.Template'>

テンプレートエンジンを指定する場合

django.template.loader.engines: Templates | Django documentation

Djangoはテンプレートエンジンの切替に対応しており、複数のテンプレートエンジンを実行時に切り替えて使うこともできます。 こちらの場合は django.template.engines でエンジンを指定して利用可能です。

>>> from django.template import engines
>>> django_engine = engines["django"]
>>> template = django_engine.from_string("今日の日付: {% now 'Y-m-d' %}\nコンテキストで渡した値: {{ spam }}")
>>> template.render({"spam": "egg"})
'今日の日付: 2023-07-14\nコンテキストで渡した値: egg'

template.render() の引数にdictを渡す必要があります。 Context クラスのインスタンスを渡すとエラーになります。

>>> template.render(Context({"spam": "egg"}))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/vagrant/tmp/venv/lib/python3.10/site-packages/django/template/backends/django.py", line 57, in render
    context = make_context(
  File "/home/vagrant/tmp/venv/lib/python3.10/site-packages/django/template/context.py", line 278, in make_context
    raise TypeError(
TypeError: context must be a dict rather than Context.

こちらの template インスタンスのクラスは、 django.template.backends.django.Template となっています。

>>> type(template)
<class 'django.template.backends.django.Template'>

インタフェースの違いと、どちらを使うほうがよいか

Template: Templates | Django documentation

django.template.base.TemplateDjangoの初期のころからある実装です。こちらはコンパイルされたテンプレートオブジェクトを表しています。

テンプレートエンジン切替に対応した django.template.backends.django.TemplateDjango 1.8で実装されたものです。 django.template.Template の薄いラッパーであるとドキュメントに説明がありました。

ドキュメントの説明だと、現時点ではテンプレートのインスタンスget_templatefrom_string メソッドで取得する想定のようなので、上記に記載した方法だと後者のテンプレートエンジンを指定する方法にしておくのが無難そうです。

それぞれインターフェースに微妙な違いがあるので注意が必要です。