Jinja在HTML中渲染文本,保留换行符

时间:2013-09-06 17:00:38

标签: python flask jinja2

我有一个这样的简单形式:

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

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

para1

para2

para3

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

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

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

- &GT;

<td>para1 para2 para3</td>

如何让它显示多行?

4 个答案:

答案 0 :(得分:21)

所有空格(包括换行符)都会在HTML中转换为单个空格。

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

  1. white-space: pre-wrap;放在包含元素上。这告诉HTML显示与源中显示的完全相同的所有空白,包括换行符。 (你也可以使用<pre>标签,但这也会禁用你可能不想要的自动换行。)
  2. 将纯文本视为Markdown并向其投掷Markdown处理器--Markdown执行的操作之一就是在<p>中包装段落。
  3. 在Python-land中,.replace('\n', '<br>')。但这会让你容易受到XSS的攻击,因为字符串中可能还有其他类似HTML的垃圾,并且修复这个问题有点痛苦。

答案 1 :(得分:2)

作为suggested by Martijn Pieters(通过链接Flask snippet 28),也有可能为此添加一个自定义过滤器。该链接已过时,因为烧瓶摘要为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 Dan的代码片段使用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 }}

答案 2 :(得分:1)

我已根据此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

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

答案 3 :(得分:-1)

如何使用<br/>代码

存储您的数据
para1
<br/>
para2
<br/>
para3