あなたが取ることができる2つの合理的なアプローチがあります。
解決策1
安全でない入力とHTMLを1つの変数に結合しているflask.Markup
ので、これを行うには実際には非常に便利な方法です。基本的な考え方は、改行文字でテキストを分割し、信頼できない各行をHTMLでエスケープしてから、信頼できる<br />
タグで結合してそれらを接着することです。
これを実証するための完全なアプリは次のとおりです。質問と同じbar.html
テンプレートを使用します。footext
自動エスケープをオフにすることが問題の安全な解決策ではない理由のデモンストレーションとして、いくつかの安全でないHTMLをに追加したことに注意してください。
import flask
app = flask.Flask(__name__)
footext = """f
o
<script>alert('oops')</script>
o"""
@app.route("/foo")
def foo():
text = ""
for line in footext.split('\n'):
text += flask.Markup.escape(line) + flask.Markup('<br />')
return flask.render_template("bar.html", text=text)
if __name__ == "__main__":
app.run(debug=True)
解決策2
もう1つのオプションは、複雑さをテンプレートにプッシュして、はるかに単純なビューを残すことです。行に分割するだけfootext
で、テンプレート内でループすることができ、自動エスケープによってこれを安全に保つことができます。
よりシンプルなビュー:
@app.route("/foo")
def foo():
return flask.render_template("bar.html", text=footext.split('\n'))
テンプレートbar.htmlは次のようになります。
<html>
{%- for line in text -%}
{{ line }}
{%- if not loop.last -%}
<br />
{%- endif -%}
{%- endfor -%}
</html>
結論
私は個人的にソリューション2を好みます。これは、レンダリングに関する懸念事項(行は<br />
タグで区切られている)を、それらが属するテンプレートに配置するためです。将来、これを変更して、たとえば、箇条書きの行を代わりに表示したい場合は、コードではなく、テンプレートを変更するだけで済みます。