模板 — Flask 文档

来自菜鸟教程
Flask/docs/2.0.x/templating
跳转至:导航、​搜索

模板

Flask 利用 Jinja2 作为其模板引擎。 您显然可以自由使用不同的模板引擎,但您仍然必须安装 Jinja2 才能运行 Flask 本身。 此要求是启用丰富扩展所必需的。 扩展可能取决于 Jinja2 的存在。

本节仅快速介绍 Jinja2 是如何集成到 Flask 中的。 如果您想了解有关模板引擎语法本身的信息,请前往官方 Jinja2 模板文档 获取更多信息。

Jinja 设置

除非自定义,Jinja2 由 Flask 配置如下:

  • 使用 render_template() 时,所有以 .html.htm.xml 以及 .xhtml 结尾的模板都启用了自动转义。
  • 使用 render_template_string() 时为所有字符串启用自动转义。
  • 模板可以使用 {% autoescape %} 标签选择加入/退出自动转义。
  • 除了默认存在的值之外,Flask 还在 Jinja2 上下文中插入了几个全局函数和助手。


标准上下文

默认情况下,Jinja2 模板中提供以下全局变量:

config

当前配置对象(flask.Flask.config

0.6 版中的新功能。

在 0.10 版更改:现在始终可用,即使在导入的模板中也是如此。

request
当前请求对象(flask.request)。 如果模板是在没有活动请求上下文的情况下呈现的,则此变量不可用。
session
当前会话对象 (flask.session)。 如果模板是在没有活动请求上下文的情况下呈现的,则此变量不可用。
g
全局变量的请求绑定对象 (flask.g)。 如果模板是在没有活动请求上下文的情况下呈现的,则此变量不可用。
url_for()
flask.url_for() 功能。
get_flashed_messages()
flask.get_flashed_messages() 功能。

Jinja 上下文行为

这些变量被添加到变量的上下文中,它们不是全局变量。 不同之处在于默认情况下这些不会显示在导入模板的上下文中。 这部分是由性能考虑引起的,部分是为了使事情明确。

这对你意味着什么? 如果您有要导入的宏,则需要访问请求对象,您有两种可能性:

  1. 您明确地将请求作为参数或您感兴趣的请求对象的属性传递给宏。
  2. 您“带上下文”导入宏。

使用上下文导入如下所示:

{% from '_helpers.html' import my_macro with context %}

控制自动转义

自动转义是为您自动转义特殊字符的概念。 HTML(或 XML,以及 XHTML)意义上的特殊字符是 &><" 以及 [ X127X]。 因为这些字符本身在文档中具有特定的含义,所以如果要将它们用于文本,则必须将它们替换为所谓的“实体”。 不这样做不仅会使用户因无法在文本中使用这些字符而感到沮丧,而且还会导致安全问题。 (参见 跨站脚本 (XSS)

但是有时您需要在模板中禁用自动转义。 如果您想将 HTML 显式注入页面,则可能是这种情况,例如,如果它们来自生成安全 HTML(如 Markdown 到 HTML 转换器)的系统。

有以下三种方法可以实现:

  • 在 Python 代码中,将 HTML 字符串包装在 Markup 对象中,然后再将其传递给模板。 这通常是推荐的方式。
  • 在模板中,使用 |safe 过滤器将字符串显式标记为安全 HTML (模板:Myvariable)
  • 暂时完全禁用自动转义系统。

要在模板中禁用自动转义系统,您可以使用 {% autoescape %} 块:

{% autoescape false %}
    <p>autoescaping is disabled here
    <p>{{ will_not_be_escaped }}
{% endautoescape %}

每当您这样做时,请非常小心您在此块中使用的变量。


注册过滤器

如果你想在 Jinja2 中注册你自己的过滤器,你有两种方法可以做到这一点。 您可以手动将它们放入应用程序的 jinja_env 中,也可以使用 template_filter() 装饰器。

以下两个示例工作相同,并且都反转对象:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

在装饰器的情况下,如果您想使用函数名称作为过滤器的名称,则该参数是可选的。 注册后,您可以像 Jinja2 的内置过滤器一样在模板中使用过滤器,例如,如果您在上下文中有一个名为 mylist 的 Python 列表:

{% for x in mylist | reverse %}
{% endfor %}

上下文处理器

为了将新变量自动注入模板的上下文中,Flask 中存在上下文处理器。 上下文处理器在呈现模板之前运行,并且能够将新值注入模板上下文。 上下文处理器是一个返回字典的函数。 然后,对于应用程序中的所有模板,此字典的键和值将与模板上下文合并:

@app.context_processor
def inject_user():
    return dict(user=g.user)

上面的上下文处理器使名为 user 的变量在模板中可用,其值为 g.user。 这个例子不是很有趣,因为 g 无论如何都可以在模板中使用,但它给出了它是如何工作的想法。

变量不限于值; 上下文处理器还可以使函数可用于模板(因为 Python 允许传递函数):

@app.context_processor
def utility_processor():
    def format_price(amount, currency="€"):
        return f"{amount:.2f}{currency}"
    return dict(format_price=format_price)

上面的上下文处理器使 format_price 函数可用于所有模板:

{{ format_price(0.33) }}

您还可以构建 format_price 作为模板过滤器(请参阅 Registering Filters),但这演示了如何在上下文处理器中传递函数。