在烧瓶中禁用autoescape

thk*_*ang 9 python flask

我想向用户显示一些文字.我发送的字符串变量有多个换行符,我不想\n显示.所以我做了:

footext = """f
o
o"""

#footext == "f\no\no"

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

bar.html:

<html>
{{ text }}
</html>
Run Code Online (Sandbox Code Playgroud)

但是启用了自动视图,我看到的是f<br />o<br />o.我的方法也不安全,我希望除了<br />从文本中转义之外的每个标签.我看了一下flask.Markup模块,然而它们也没有真正起作用.

这样做的正确方法是什么?

Day*_*Day 8

您可以采取两种合理的方法.

解决方案1

正如您将不安全的输入与HTML组合到一个变量flask.Markup中实际上是一种非常方便的方法.基本的想法是在换行符上拆分文本,确保HTML转义您不信任的每一行,然后将它们粘合在一起,由<br />您信任的标记连接在一起.

这是完整的应用程序来演示这一点.它使用与bar.html您的问题相同的模板.请注意,我添加了一些不安全的HTML footext作为示例,说明为什么关闭自动转换不是解决问题的安全方法.

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)
Run Code Online (Sandbox Code Playgroud)

解决方案2

另一种选择是将复杂性推向模板,让您看到更简单的视图.只需分成footext几行,然后你就可以在你的模板中循环它,autoescaping将负责保持这个安全.

更简单的观点:

@app.route("/foo")
def foo():
    return flask.render_template("bar.html", text=footext.split('\n'))
Run Code Online (Sandbox Code Playgroud)

模板bar.html变为:

<html>
    {%- for line in text -%}
        {{ line }}
        {%- if not loop.last -%}
            <br />
        {%- endif -%}
    {%- endfor -%}
</html>
Run Code Online (Sandbox Code Playgroud)

结论

我个人更喜欢解决方案2,因为它将渲染问题(行由<br />标签分隔)放在它们所属的模板中.如果您以后想要更改此内容,比如在项目符号列表中显示行,则只需更改模板,而不是代码.


Rya*_*ona 6

我将把我之前的答案作为一个榜样.

对于这种事情,一个非常好的解决方案是自定义过滤器,它允许您使用诸如的语法

{{ block_of_text | nl2br }}
Run Code Online (Sandbox Code Playgroud)

方便地,您可以使用nl2br过滤器代码段(或轻松自定义)!