模板

Flask利用Jinja2作为其模板引擎。显然,您可以自由地使用不同的模板引擎,但是您仍然需要安装Jinja2来运行Flask本身。这个要求对于启用丰富的扩展是必要的。扩展可以依赖于Jinja2的存在。

本节只简单介绍了如何将金贾2集成到烧瓶中。如果您想了解模板引擎语法本身的信息,请到官员那里。 Jinja2 Template Documentation 更多信息。

Jinja设置

Jinja2 默认配置如下:

  • 为所有以结尾的模板启用自动转义 .html.htm.xml.xhtml ,以及 .svg 在使用时 render_template()

  • 当使用 render_template_string() 时,字符串开启 自动转义

  • 模板可以选择使用 {{% autoescape %}} 标签来手动设置是否转义。

  • Flask 在Jinja2 环境中加入一些全局函数和辅助对象,以增强模板的功能。

标准环境

默认情况下,以下全局变量可以在jinja2模板中使用:

config

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

Changelog

在 0.10 版本发生变更: 现在,即使在导入的模板中,它也始终可用。

在 0.6 版本加入.

request

当前请求对象( flask.request )如果模板在没有活动请求环境的情况下渲染,则此变量不可用。

session

当前会话对象( flask.session )如果模板在没有活动请求环境的情况下渲染,则此变量不可用。

g

全局变量的请求绑定对象( flask.g )如果模板在没有活动请求环境的情况下渲染,则此变量不可用。

url_for()

func:`flask.url_for`函数 。

get_flashed_messages()

flask.get_flashed_messages() 函数。

Jinja 语境行为

这些被添加到变量的语境中的变量,它们不是全局变量。不同之处在于,默认情况下,它们不会显示在导入模板的环境中。这部分是由于性能方面的原因,同时也考虑让代码更有条理。

这对你来说意味着什么?如果有要导入的宏,则需要访问请求对象,那么你有两种选择:

  1. 显式地把请求或都该请求有用的属性作为参数传递给宏。

  2. 导入“with context”宏。

导入方式如下:

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

控制自动转义

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

但是,有时需要禁用模板中的自动转义。如果你想要显式地将HTML植入页面,例如,如果页面来自一个生成安全HTML的系统,比如标记为HTML的转换器,那么就可能出现这种情况。

有三种方法可以控制自动转义:

  • 在Python代码中,将HTML字符串包装在 Markup 对象,然后将其传递给模板。这通常是推荐的方式。

  • 在模板内,使用 |safe 筛选以将字符串显式标记为安全HTML( {{{{ myvariable|safe }}}}

  • 临时完全禁用自动转义系统。

要在模板中禁用自动转义系统,可以使用 {{% 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

对于decorator,如果要使用函数名作为筛选器的名称,则参数是可选的。注册后,你可以使用模板中的过滤器,方法与Jinja2的内置过滤器相同,例如,假设在环境中你有一个 名为 mylist 的 Pyhton 列表:

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

环境处理器

为了将新变量自动注入模板的环境中,环境处理器在模板被渲染前运行,因此可以把新的变量自动引入模板环境中。它是一个函数,返回一个字典的函数。这个字典的键值最终将传入应用中所有模板的环境中:

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

上例中的环境处理器创建了一个值为 g.user 的 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 创建为一个模板过滤器(参见 注册过滤器 ),这里只是演示如何在一个环境处理器中传递函数。

不将整个模板呈现为一个完整的字符串,而是将其呈现为流,从而生成较小的增量字符串,这可能很有用。这可以用于以块为单位传输HTML,以加快初始页面加载速度,或者在呈现非常大的模板时节省内存。

JJIA2模板引擎支持逐段呈现模板,返回字符串迭代器。烧瓶提供了 stream_template()stream_template_string() 函数以使其更易于使用。

from flask import stream_template

@app.get("/timeline")
def timeline():
    return stream_template("timeline.html")

这些函数会自动将 stream_with_context() 包装(如果请求处于活动状态),以便它在模板中保持可用。