9

ユーザーにテキストを表示したい。\n送信している文字列変数に複数の改行文字が含まれているため、表示したくありません。だから私はしました:

footext = """f
o
o"""

#footext == "f\no\no"

@app.route("/someurl")
def foo():
    return render_template("bar.html", text = footext.replace("\n", "<br />"))

bar.html:

<html>
{{ text }}
</html>

ただし、自動エスケープが有効になっていて、表示されるのはですf<br />o<br />o。また、私の方法は安全ではありません<br />。テキストからエスケープする以外のすべてのタグが必要です。私はflask.Markupモジュールを調べましたが、実際には機能しません。

これを行うための適切な方法は何ですか?

4

3 に答える 3

9

あなたが取ることができる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 />タグで区切られている)を、それらが属するテンプレートに配置するためです。将来、これを変更して、たとえば、箇条書きの行を代わりに表示したい場合は、コードではなく、テンプレートを変更するだけで済みます。

于 2013-01-29T23:31:49.240 に答える
6

悪い例として前の答えを残しておきます。

この種のものの非常に良い解決策は、カスタムフィルターです。これにより、次のような構文を使用できます。

{{ block_of_text | nl2br }}

これは、便利なことに、このnl2brフィルタースニペットを使用して実行できます(または簡単にカスタマイズできます)。

于 2013-01-30T02:53:02.793 に答える
1

Jinja2テンプレートで自動エスケープをオフにするか、rawブロックを使用します

于 2013-01-29T21:46:32.630 に答える