Jinja2でHTMLをエスケープして、JavaScript(jQuery)で文字列として使用できるようにするにはどうすればよいですか?
Djangoのテンプレートシステムを使用している場合、次のように書くことができます。
$("#mydiv").append("{{ html_string|escapejs }}");
Djangoの |escapejs
filter は、このコードブロックの使用目的を壊す可能性のある、html_string
内の項目(引用符、特殊文字など)をエスケープしますが、Jinja2には同等のものがないようです。フィルタ(ここで間違っていますか?).
Djangoからコードをコピーして貼り付けるよりもクリーンな解決策はありますか?
私は昨年同様の問題に直面しました。 bottle を使用しているかどうかはわかりませんが、私のソリューションは次のようになりました。
import json
def escapejs(val):
return json.dumps(str(val)) # *but see [Important Note] below to be safe
@app.route('/foo')
def foo():
return bottle.jinja2_template('foo', template_settings={'filters': {'escapejs': escapejs}})
(template_settings
dictはどこでも使用していたので、ヘルパー関数でラップしましたが、この例では単純にしています。)
残念ながら、組み込みのjinja2フィルターほど単純ではありませんが、特に他にもいくつかのカスタムフィルターを追加する必要があることを考えると、それを使って幸せに暮らすことができました。
重要な注意:以下の彼の鋭いコメントに対する@medmundsへの帽子のヒント。json.dumpsはXSSセーフではないことを思い出させてください。 IOW、インターネットに直接接続された本番サーバーでは使用したくないでしょう。 より安全なjsonエスケープルーチン (またはDjangoの-申し訳ありませんがOPを盗む、それを避けたいと思っていたのはわかっています)を記述し、json.dumpsを使用する代わりにそれを呼び出すことをお勧めします。
これは、Jinja2テンプレートで使用するために作成したDjangoのフィルターに基づくescapejs
フィルターです。
_js_escapes = {
'\\': '\\u005C',
'\'': '\\u0027',
'"': '\\u0022',
'>': '\\u003E',
'<': '\\u003C',
'&': '\\u0026',
'=': '\\u003D',
'-': '\\u002D',
';': '\\u003B',
u'\u2028': '\\u2028',
u'\u2029': '\\u2029'
}
# Escape every ASCII character with a value less than 32.
_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in xrange(32))
def jinja2_escapejs_filter(value):
retval = []
for letter in value:
if _js_escapes.has_key(letter):
retval.append(_js_escapes[letter])
else:
retval.append(letter)
return jinja2.Markup("".join(retval))
JINJA_ENVIRONMENT.filters['escapejs'] = jinja2_escapejs_filter
テンプレートでの安全な使用例:
<script type="text/javascript">
<!--
var variableName = "{{ variableName | escapejs }}";
…
//-->
</script>
VariableNameがstr
またはunicode
の場合。
Jinja2にはNiceフィルターがあります tojson 。文字列からjsonを作成すると、二重引用符 ""で囲まれた文字列が生成されます。 javascriptで安全に使用できます。また、自分で引用符を付ける必要はありません。
$("#mydiv").append({{ html_string|tojson }});
私はこの問題を調査しました。私の解決策はフィルターを定義することです。
from flask import Flask, Markup
app = Flask(__name__)
app.jinja_env.filters['json'] = lambda v: Markup(json.dumps(v))
およびテンプレート内:
<script>
var myvar = {{myvar|json}} ;
</script>
これには、myvar JSONシリアル化できるものなら何でもよいという優れた機能があります
@tometzkyに基づいて、ここに私のPython 3バージョン:
_js_escapes = {
'\\': '\\u005C',
'\'': '\\u0027',
'"': '\\u0022',
'>': '\\u003E',
'<': '\\u003C',
'&': '\\u0026',
'=': '\\u003D',
'-': '\\u002D',
';': '\\u003B',
u'\u2028': '\\u2028',
u'\u2029': '\\u2029'
}
# Escape every ASCII character with a value less than 32.
_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in range(32))
@register.filter
def escapejs(value):
return jinja2.Markup("".join(_js_escapes.get(l, l) for l in value))
使い方はまったく同じです。