我想向用户显示一些文字。我发送的字符串变量有多个换行符,我不希望显示\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模块,然而它们也没有真正起作用。
这样做的正确方法是什么?
答案 0 :(得分:8)
您可以采取两种合理的方法。
当您将不安全的输入与HTML组合到单个变量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)
另一种选择是将复杂性推向模板,让您拥有更简单的视图。只需将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 />
标记分隔)放在它们所属的模板中。如果您以后想要更改此内容,比如在项目符号列表中显示行,则只需更改模板,而不是代码。
答案 1 :(得分:6)
我将my previous answer作为错误的示例。
这种事情的一个非常好的解决方案是custom filter,它可以让你使用诸如
之类的语法{{ block_of_text | nl2br }}
,方便地,您可以使用this nl2br
filter snippet(或轻松自定义)!
答案 2 :(得分:1)
在Jinja2模板中转动autoescaping off,或使用raw block。