使用 Jinja 保留渲染为 HTML 的文件中的换行符

问题描述 投票:0回答:3

我正在尝试打印网页中文件的内容。 我想在单独的行上打印文件中的每一行,但缺少换行符。 如何打印文件并保留换行符?

@app.route('/users')
def print_users():
    v = open("users.txt","r").read().strip()
    # also tried:
    # v = open("users.txt","r").read().strip().split('\n')
    return render_template('web.html', v=v)
{{ v|safe}}
python html flask jinja2
3个回答
3
投票

您可以使用:

v = open("users.txt","r").readlines()
v = [line.strip() for line in v]

然后在你的html中添加类似的内容(但随意使用它):

<form action="/print_users"  method="post" >    
                    <div class="form-inline">

                  {% for line in v %}
                      <div>{{ line|safe}}</div>
                  {% endfor %}


    <input class="btn btn-primary" type="submit"  value="submit" > 
              </div>

                    </form> 

1
投票

虽然其他答案提供了很好的技术并且当前接受的解决方案有效,但我需要执行类似的任务(呈现文本电子邮件模板),但需要扩展它以保留文件中宏的处理,这导致我创建我认为最简单、最优雅的解决方案是使用 render_template_string。

def show_text_template(template_name):
    """
    Render a text template to screen.
    Replace newlines with <br> since rendering a template to html will lose the line breaks
    :param template_name: the text email template to show
    :return: the text email, rendered as a template
    """
    from flask import render_template_string

    txt_template = open(
        '{}/emails/{}{}'.format(app.config.root_path + '/' + app.template_folder, template_name, '.txt'),
        "r").readlines()

    return render_template_string('<br>'.join(txt_template))

0
投票

解决方案是使用

nl2br
Jinja 过滤器

from markupsafe import Markup, escape

def nl2br(value):
    """Securely replace all newline characters '\n' by HTML '<br>' break tags."""

    safe_value = str(escape(value))
    formatted_value = safe_value.replace("\n", "<br>")

    return Markup(formatted_value)
<p> {{ yourinputstring | nl2br }} </p>

为了解释,您希望将输入字符串中的换行符

\n
替换为输出模板中的 HTML 换行符标记
<br>

问题在于,出于安全原因(特别是为了防止

XSS 漏洞
),Jinja 会转义特殊字符,例如
<
>。因此,如果您只是将
\n
字符替换为
<br>
标签,它们将被转义并且不起作用。

<p> {{ yourinputstring | safe }} </p> <!-- DON'T DO THIS -->

您可以要求模板中的 Jinja 不要使用

safe
过滤器转义字符,但这会使您容易受到 XSS 攻击(尤其是当输入来自用户时)。强烈建议不要这种做法。

我不知道为什么这没有在本地实现,但唯一的解决方案是使用自定义过滤器。

MarkupSafe
是Jinja和Flask使用的模块,所以它应该已经安装了。


如果您使用 Flask,您的代码将如下所示:

from flask import Flask, render_template
from markupsafe import Markup, escape

server = Flask(__name__)

@server.template_filter()
def nl2br(value):
    """Securely replace all newline characters '\\n' by HTML '<br>' break tags."""

    safe_value = str(escape(value))
    formatted_value = safe_value.replace("\n", "<br>")

    return Markup(formatted_value)

@server.route("/index.html")
def index():
    input_string = "hello, world!\n"
    dangerous_input = "<script>alert('XSS');</script>"
    
    return render_template("index.html", input_1=input_string, input_2=dangerous_input)

if __name__ == "__main__": 
    server.run(debug=True, port=8080)

使用

index.html
模板为:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jinja custom filter for newline characters</title>
</head>
<body>
        <p>{{ input_1 | nl2br }}<p>
        <p>{{ input_2 | nl2br }}</p>
</body>
</html>

渲染的 HTML 看起来像这样,有效地将

\n
转换为
<br>
,同时防止 XSS 攻击:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jinja custom filter for newline characters</title>
</head>
<body>
    <p>hello, world!<br><p>
    <p>&lt;script&gt;alert(&#39;XSS&#39;);&lt;/script&gt;</p>
</body>
</html>

顺便说一句,有人绝对应该建议 Jinja 维护者在本地实现这个,因为它似乎是非常基本且普遍有用的东西。

© www.soinside.com 2019 - 2024. All rights reserved.