模板

Flask leverages Jinja2 as template engine. 当然,你也可以自由使用其它的模板引擎,但运行Flask本身仍然需要Jinja2依赖。这对启用富扩展是必要的。扩展可以依赖Jinja2存在。

This section only gives a very quick introduction into how Jinja2 is integrated into Flask. 如果你需要更多关于模板引擎本身的信息, 请参考官方Jinja2模板文档

Jinja配置

Unless customized, Jinja2 is configured by Flask as follows:

  • 当使用render_template()时,所有扩展名为.html, .htm, .xml以及.xhtml的模板会开启自动转义。
  • 当使用render_template_string()时,所有字符串都开启字典转义。
  • 模板可以利用{% autoescape %}标签选择自动转义的开关。
  • Flask inserts a couple of global functions and helpers into the Jinja2 context, additionally to the values that are present by default.

标准上下文

The following global variables are available within Jinja2 templates by default:

config

The current configuration object (flask.config)

New in version 0.6.

Changed in version 0.10: This is now always available, even in imported templates.

request

The current request object (flask.request). 当模版不是在活动的请求上下文中渲染时这个变量不可用。

session

The current session object (flask.session). 当模版不是在活动的请求上下文中渲染时这个变量不可用。

g

The request-bound object for global variables (flask.g). 当模版不是在活动的请求上下文中渲染时这个变量不可用。

url_for()

The flask.url_for() function.

get_flashed_messages()

The flask.get_flashed_messages() function.

Jinja上下文行为

These variables are added to the context of variables, they are not global variables. The difference is that by default these will not show up in the context of imported templates. 这样做,一方面是考虑到性能,另一方面是为了让事情显式透明。

What does this mean for you? If you have a macro you want to import, that needs to access the request object you have two possibilities:

  1. you explicitly pass the request to the macro as parameter, or the attribute of the request object you are interested in.
  2. 与上下文一起(with context)导入宏。

与上下文中一起(with context)导入的方式如下:

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

标准过滤器

These filters are available in Jinja2 additionally to the filters provided by Jinja2 itself:

tojson()

这个函数把给定的对象转换为 JSON 表示。如果你要动态生成 JavaScript 这里有 一个非常有用的例子。

注意script标签里的东西不应该被转义,因此如果你想在script标签里使用它, 请使用|safe来禁用转义:

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

控制自动转义

Autoescaping is the concept of automatically escaping special characters for you. Special characters in the sense of HTML (or XML, and thus XHTML) are &, >, <, " as well as '. Because these characters carry specific meanings in documents on their own you have to replace them by so called “entities” if you want to use them for text. Not doing so would not only cause user frustration by the inability to use these characters in text, but can also lead to security problems. (see Cross-Site Scripting (XSS))

然而,你有时会需要在模板中禁用自动转义。比如在页面中显式地插入 HTML , 可以是一个来自于 markdown 到 HTML 转换器的安全输出。

There are three ways to accomplish that:

  • In the Python code, wrap the HTML string in a Markup object before passing it to the template. This is in general the recommended way.
  • 在模板中,使用|safe过滤器显式地标记一个字符串为安全的 HTML({{ myvariable|safe }})。
  • Temporarily disable the autoescape system altogether.

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

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

Whenever you do this, please be very cautious about the variables you are using in this block.

注册过滤器

If you want to register your own filters in Jinja2 you have two ways to do that. You can either put them by hand into the jinja_env of the application or use the template_filter() decorator.

The two following examples work the same and both reverse an object:

@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

In case of the decorator the argument is optional if you want to use the function name as name of the filter. Once registered, you can use the filter in your templates in the same way as Jinja2’s builtin filters, for example if you have a Python list in context called mylist:

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

上下文处理器

To inject new variables automatically into the context of a template, context processors exist in Flask. Context processors run before the template is rendered and have the ability to inject new values into the template context. 上下文处理器是一个返回字典的函数。这个字典的键值最终将传入应用中所有模板的上下文:

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

The context processor above makes a variable called user available in the template with the value of g.user. This example is not very interesting because g is available in templates anyways, but it gives an idea how this works.

Variables are not limited to values; a context processor can also make functions available to templates (since Python allows passing around functions):

@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)

The context processor above makes the format_price function available to all templates:

{{ format_price(0.33) }}

You could also build format_price as a template filter (see Registering Filters), but this demonstrates how to pass functions in a context processor.