Flask: 模版

引言

模版是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体指只在请求的上下文中才能知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为 渲染 。为了渲染模版, Flask 使用了一个名为 Jinja2 的强大模版引擎。

Jinja2 模版引擎

形式最简单的Jinja2模版就是一个包含响应文本的文件。

示例 1 templates/index.html

<h1>Hello World!</h1>

示例 2 templates/user.html

<h1>Hello, {{ name }}!</h1>

示例2 中包含一个使用变量表示的动态部分 {{ name }}

渲染模版

默认情况下, Flask 在程序文件夹中的 templates 子文件夹中寻找模版。我们将 示例1 和 示例2 分别命名为 index.htmluser.html 存放在 templates 文件夹下。

视图函数对应为:

from flask import Flask, render_template

#...

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/user/<name>')
def user(name):
    return render_template('user.html', name=name)

Flask 提供的 render_template 函数把 Jinja2 模版引擎集成到程序中。 render_template 函数的第一个参数是模版的文件名。随后的参数都是键值对, 表示模版中变量对应的真实值。在这段代码中,第二个模版收到一个名为 name 的变量。

视图函数中 name=name 是关键字参数,左边的 name 表示参数名,就是模版中的占位符;右边的 name 是当前作用域中的变量,表示同名参数的值。

变量

示例2 在模版中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符, 告诉模版引擎这个位置的值从渲染模版时使用的数据中获取。

Jinja2 能识别所有类型的变量,甚至 列表、字典和对象。在模版中使用变量的一些示例如下:

<p>A vakue from a dictionary: {{ mydict['key'] }}.</p>
<p>A vakue from a list: {{ mylist[3] }}.</p>
<p>A vakue from a list, with a variable index: {{ mylist[myintvar] }}.</p>
<p>A vakue from a object's method: {{ myobj.somemethod() }}.</p>

可以使用 过滤器 修改变量, 过滤器名添加在变量名之后, 中间使用竖线分隔。例如,下述模版以首字母大写形式显示变量 name 值:

Hello, {{ name|capitalize }}

常用过滤器:

过滤器名 说明
safe 渲染值时不转义
capitalize 把值的首字母转换成大写,其他字母转换成小写
lower 把值转换成小写形式
upper 把值转换成大写形式
title 把值中的每个单词的首字母都转成大写
trim 把值的首尾空格去掉
scriptags 渲染之前把值中所有的 HTML 标签都删掉

注意:千万别在不可信的值上使用 safe 过滤器,例如用户在表单中输入的文本。
默认情况下,出于安全考虑, Jinja2 会转移所有变量。例如, 如果一个变量的值为 '<h1>Hello</h1>'Jinja2 会将其渲染成 '&lt;h1&gt;Hello&lt;/h1&gt;',浏览器能显示 h1 元素,但不会进行解释。

控制结构

Jinja2 提供了多种控制结构,可用来改变模版的渲染流程。

条件控制语句

{% if user %}
    Hello, {{ user }}
{% else %}
    Hello, Stranger!
{% endif %}

for 循环

<ul>
    {% for comment in comments %}
        <li>{{ comment }}</li>
    {% endfor %}
</ul>

宏类似 python 中的函数

{% macro render_comment(comment) %}
    <li>{{ comment }}</li>
{% endmacro %}

<ul>
    {% for comment in comments %}
        {{ render_comment(comment) }}
    {% endfor %}
</ul>

包含

需要在多出重复使用的模版代码片段可以写入单独的文件,再包含在所有模块中,以避免重复:

{% include 'common.html' %}

继承

另一种重复使用代码的强大方式是模版集成,它类似与 Python 代码中的类继承。首先, 创建一个名为 base.html 的基模版:

<html>
<head>
    {% block head %}
    <title>{% block title%}{% endblock %} - My Application<title>
    {% endblock %}
</head>
<body>
    {% block body %}
    {% endblock %}
</body>
</head>

block 标签定义的元素可在衍生模版中修改。在 base.html 中,我们定义了名为 headtitlebody 的块。注意, title 包含在 head 中。 下面这个示例是基模版的衍生模版:

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
    {{ supper() }}
    <style>
    </style>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}

extends 指令声明这个模版衍生自 base.html。在 extends 指令后, 基模版中的 3 个块被重新定义, 模版引擎会将其插入适当的位置。注意新定义的 head 块, 在基模版中其内容不是空的, 所以使用 super() 获取原来的内容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章