模板

Flask利用Jinja2作为模板引擎。显然,你可以自由使用不同的模板引擎,但仍然需要安装jinja2来运行Flask本身。此要求对于启用富扩展是必需的。扩展可取决于Jinja2是否存在。

本文只是简单介绍如何在 Flask 中使用 Jinja2 。如果要详细了解 Jinja2 语法本身的信息,请查阅 Jinja2 模板官方文档 。

Jinja设置

Jinja2 默认配置如下:

  • 当使用 render_template() 时,扩展名为 .html 、 .htm 、 .xml 和 .xhtml 的模板中开启自动转义。
  • 当使用 render_template_string() 时,字符串开启 自动转义
  • 模板可以选择使用 {{% autoescape %}} 标签来手动设置是否转义。
  • Flask 在Jinja2 环境中加入一些全局函数和辅助对象,以增强模板的功能。

标准环境

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

config

当前配置对象( flask.config

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

0.6 新版功能.

Changelog
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 %}

标准过滤器

除Jinja2自身提供的过滤器外,Jinja2还提供这些过滤器:

tojson()

此函数将给定对象转换为JSON格式。例如,如果你要动态生成JavaScript,这将非常有用。

<script type=text/javascript>
    doSomethingWith({{ user.username|tojson }});
</script>

single-quoted HTML属性中使用JSON也是很安全的:

<button onclick='doSomethingWith({{ user.username|tojson }})'>
    Click me
</button>

注意,在 script 标记内部不能转义,因此在 Flask 0.10 之前的版本中, 如果要在 script 标记内部使用这个函数必须用 |safe 关闭转义:

控制自动转义

自动转义是指自动对特殊字符进行转义。特殊字符是指 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=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

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

{{ format_price(0.33) }}

你还可以把 format_price 创建为一个模板过滤器(参见 注册过滤器 ),这里只是演示如何在一个环境处理器中传递函数。