Django Template Languageでの変数のエスケープ回避

Django Template Language(DTL)でのエスケープメモ

htmlレンダリングで使うDTLのデフォルトでは、変数を展開すると、自動で文字実体参照などの実体参照に置き換えられてしまう。(エスケープされてしまう。)

html要素(htmlタグ)を変数を使って埋め込みたいなど、変数をそのままレンダリングしたい(非エスケープしたい)ときもある。その方法を2つ挙げる。

環境

  • Django==3.0.8

safeフィルターを利用

Djangoにビルトインされたsafeフィルタを使えば、変数展開時にエスケープさせずにおける。参考:Built-in template tags and filters | Django documentation | Django

変数をいつも通り{{ }}で囲み、safeフィルタを通すだけ。

{{ h1_hello }}
{{ h1_hello|safe }}

そして変数に次の値を格納する:

context = {'h1_hello': '<h1>こんにちは</h1>'}

この出力は次のようになる:

&lt;h1&gt;こんにちは&lt;/h1&gt;
<h1>こんにちは</h1>

このようにsafeフィルタを通せば、エスケープされずに出力される。

変数を展開するごとに|safeをつける必要がある。

autoescapeタグを利用

Djangoにビルトインされたautoescapeタグを使えば、囲ったブロックをまとめてエスケープせずにおける。参考:Built-in template tags and filters | Django documentation | Django

エスケープしたくないところを{% autoescape off %}{% endautoescape %}で挟めばいい。 offonにすればエスケープされる。DTLでは自動エスケープがデフォルトでオンになっている。

{% autoescape on %}
{{ h1_hello }}
{{ two_elements_text }}
{% endautoescape %}

{% autoescape off %}
{{ h1_hello }}
{{ two_elements_text }}
{% endautoescape %}

変数の値を次にようにする:

context = {
    'h1_hello': '<h1>こんにちは</h1>',
    'two_elements_text': """
        <h1>今日も</h1>
        <p>いい天気。</p>
    """
}

すると出力は次のようになる:

&lt;h1&gt;こんにちは&lt;/h1&gt;
&lt;h1&gt;今日も&lt;/h1&gt;
&lt;p&gt;いい天気。&lt;/p&gt;

<h1>こんにちは</h1>
<h1>今日も</h1>
<p>いい天気。</p>

本当は、two_elements_textstr.strip()しないと、改行やインデントが酷くなる。サンプルでは修正した。

このタグは入れ子にして内側で再度onにもできる。また、{% autoescape off %}タグの中ならincludeしたテンプレート内でも、自動エスケープしなくなる点には注意する。

使い分ける

safeフィルタは局所的にエスケープの回避ができる。autoescapeタグはブロック単位で制御できる。

safeフィルタばかり書いて大変だなと思ったらautoescapeタグの利用を考えるくらいでいいだろう。

autoescapeタグは中身の子テンプレートにも影響が行くので、おかしいと思ったら確認すること。

以上です。


広告

https://amzn.to/2BHWWp7
タイトルとURLをコピーしました