【问题标题】:Jinja render text in HTML preserving line breaksJinja 在 HTML 中渲染文本,保留换行符
【发布时间】:2020-09-24 17:20:12
【问题描述】:

我有一个这样的简单表格:

class RecordForm(Form):    
    notes = TextAreaField('Notes')

我将数据记录在三个段落中:

para1

para2

para3

在模板中,我希望以只读方式查看该记录的内容。 (不可编辑的表格)

记录是这种情况下包含数据的模型:

<td>{{ record.notes }}</td>

-->

<td>para1 para2 para3</td>

我该怎么做才能显示多行?

【问题讨论】:

标签: python flask jinja2


【解决方案1】:

所有空格,包括换行符,在 HTML 中都变成了一个空格。

您的选择,从最好到最差:

  1. white-space: pre-wrap; 放在包含元素上。这告诉 HTML 完全按照它在源代码中的显示方式显示所有空格,包括换行符。 (您也可以使用&lt;pre&gt; 标签,但这也会禁用自动换行,这可能是您不想要的。)
  2. 将纯文本视为 Markdown 并对其进行 Markdown 处理器处理 - Markdown 所做的其中一项工作是将段落包装在 &lt;p&gt; 中。
  3. 在 Python 领域,执行 .replace('\n', '&lt;br&gt;')。但这会使您容易受到 XSS 的攻击,因为字符串中可能存在其他类似 HTML 的垃圾,修复它有点麻烦。

【讨论】:

  • 查看 flask.pocoo.org/snippets/28 了解 Flask / Jinja2 特定选项将换行符转换为 &lt;br&gt; 标签确保任何嵌入的 HTML 都安全呈现。
【解决方案2】:

作为suggested by Martijn Pieters(通过链接Flask snippet 28),还可以为此添加自定义过滤器。该链接已过时,因为 Flask Snippets 是 no longer provided

所以我会在这里提供the snippet from web archive

nl2br 过滤器

由 Dan Jacob 于 2010-06-17 @ 05:03 发布并归档于模板技巧

这是一个 nl2br(
换行)过滤器,改编自 Jinja2 示例:

http://jinja.pocoo.org/2/documentation/api#custom-filters

import re

from jinja2 import evalcontextfilter, Markup, escape

_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

app = Flask(__name__)

@app.template_filter()
@evalcontextfilter
def nl2br(eval_ctx, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', '<br>\n') \
        for p in _paragraph_re.split(escape(value)))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

上面关于自定义过滤器的链接似乎也已过时。这是当前稳定版本 1.1 的类似链接:https://flask.palletsprojects.com/en/1.1.x/templating/#registering-filters

我不太确定他为什么要使用如此复杂的结果计算。对我来说,以下代码有效,而且更简单。 也许,如果你不使用autoescape(我不想禁用它),上面的变体会更好?! 无论如何,现在两种变体都可用:

# custom_template_filters.py

from flask import Blueprint
from jinja2 import evalcontextfilter, Markup, escape

blueprint = Blueprint('custom_template_filters', __name__)

@evalcontextfilter
@blueprint.app_template_filter()
def newline_to_br(context, value: str) -> str:
    result = "<br />".join(re.split(r'(?:\r\n|\r|\n){2,}', escape(value)))

    if context.autoescape:
        result = Markup(result)

    return result

值得一提的是,来自 Dan Jacob 的代码 sn-p 使用 Python2,并且我通过 Blueprint 运行模板过滤器。为了完整起见,我还使用工厂方法提供了 app.py

# app.py

from flask import Flask

def create_app() -> Flask:
    app = Flask(__name__)
    ...
    register_template_filters(flask_app=app)
    return app

def register_template_filters(flask_app: Flask) -> None:
    from . import custom_template_filters
    flask_app.register_blueprint(custom_template_filters.blueprint)
    return None

这或多或少是一个实现细节,您将如何让上下文过滤器工作。主要思想在于函数nlbrnewline_to_br 本身。如果您让自定义过滤器正常工作,它可以在您的所有 Jinja 模板中使用,您可以像这样使用它:

{{ anystring | newline_to_br }}

【讨论】:

【解决方案3】:

我已根据此https://stackoverflow.com/a/60572523/12851576 答案从文档中修改了 nl2br 过滤器

import re
from jinja2 import evalcontextfilter
from markupsafe import Markup, escape


@evalcontextfilter
def nl2br(eval_ctx, value):
    """Converts newlines in text to HTML-tags"""
    result = "<br>".join(re.split(r'(?:\r\n|\r|\n)', escape(value)))

    if eval_ctx.autoescape:
        result = Markup(result)
    return result

它对我有用。 有什么缺点吗?

【讨论】:

    猜你喜欢
    • 2016-07-08
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 2018-08-21
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多