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>'}
この出力は次のようになる:
<h1>こんにちは</h1>
<h1>こんにちは</h1>
このようにsafeフィルタを通せば、エスケープされずに出力される。
変数を展開するごとに|safeをつける必要がある。
autoescapeタグを利用
Djangoにビルトインされたautoescapeタグを使えば、囲ったブロックをまとめてエスケープせずにおける。参考:Built-in template tags and filters | Django documentation | Django
エスケープしたくないところを{% autoescape off %}と{% endautoescape %}で挟めばいい。
offをonにすればエスケープされる。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>
"""
}
すると出力は次のようになる:
<h1>こんにちは</h1>
<h1>今日も</h1>
<p>いい天気。</p>
<h1>こんにちは</h1>
<h1>今日も</h1>
<p>いい天気。</p>
本当は、two_elements_textはstr.strip()しないと、改行やインデントが酷くなる。サンプルでは修正した。
このタグは入れ子にして内側で再度onにもできる。また、{% autoescape off %}タグの中ならincludeしたテンプレート内でも、自動エスケープしなくなる点には注意する。
使い分ける
safeフィルタは局所的にエスケープの回避ができる。autoescapeタグはブロック単位で制御できる。
safeフィルタばかり書いて大変だなと思ったらautoescapeタグの利用を考えるくらいでいいだろう。
autoescapeタグは中身の子テンプレートにも影響が行くので、おかしいと思ったら確認すること。
以上です。
広告


