在 Python 内部生成 HTML 不好玩,且相当笨拙。因为你必须自己负责 HTML 转义,来确保应用的安全。因此,Flask 自动为您配置 Jinja2 模板引擎
使用 render_template()
方法可以渲染模板,你只需要提供模板名称和需要作为参数传递给模板的变量就可以了
下面是一个简单的模板渲染的例子:
from flask improt render_template
@app.route("/hello/")
def view():
return render_template("index.html")
flask 将尝试在 templates
文件夹中寻找 HTML 文件。因此,如果你的应用是一个模块,那么模板文件夹应该在模块同级目录下
/run.py
/templates
/index.html
(1) 变量传值
return render_template("index.html", name="zong", age=18, hobby=["唱歌","游泳"])
<body>
<p>姓名: {{ name }}p>
<p>年龄: {{ age }}p>
<p>爱好: {{ hobby }}p>
body>
(2) 字典传值
dct = {
"name": "zong",
"age": 18,
"hobby": ["唱歌","游泳"]
}
return render_template("index.html", dct=dct)
<body>
<p>姓名: {{ dct.name }}p>
<p>年龄: {{ dct.age }}p>
<p>爱好: {{ dct.hobby }}p>
body>
变量可以通过过滤器修改,过滤器和变量用管道符号 |
分割,并且也可以用圆括号传递可选参数。多个过滤器可以链式调用,前一个多滤器的输出会被作为后一个过滤器的输入
例如 {{ name|striptags|title }}
会移除 name 中所有 HTML 标签并且改写为标题样式的大小写格式
过滤器接受带圆括号的参数,如同函数调用,如 把一个列表用逗号链接起来
{{ list|join(',') }}
常用过滤器:
过滤器 | 示例 | 描述 |
---|---|---|
striptags |
bq|striptags |
去除标签 |
reverse |
test|reverse |
字符串反转 |
default |
url|default("***") |
默认值 |
safe |
bq|safe |
将值标记为安全,不再自动转义 |
length |
[1,2,3]|length |
列表长度 |
sum |
[1,2,3]|sum |
列表求和 |
sort |
[1,2,3]|sort |
列表排序 |
自定义过滤器:
过滤器的本质是函数,当模板内置的过滤器不能满足要求,可以自定义过滤器。自定义过滤器有两种实现方式:
(1) add_temp_filter()
def my_filter(test):
return "***"
app.add_temp_filter(my_filter,"my_filter")
可以给过滤器指定一个名字,如果不指定,默认为函数名
(2) @app.template_filter
@app.template_filter("mf")
def my_filter(args):
return "***"
自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器
模板仅仅是文本文件,可以生成任何基于文本的格式(HTML,XML,CSV等)。它并没有特定的扩展名,.html
和 .xml
都是可以的
模板包含 变量 和 表达式,这两者在模板求值的时候会被替换为值。模板中还有标签,控制模板的逻辑。Jinja2 模板语法的大量灵感来自 Django 和 Python
下面是一个最小的模板:
<html">
<head>
<title>testtitle>
head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}a>li>
{% endfor %}
ul>
<h1>My Webpageh1>
{{ a_variable }}
body>
html>
这里有两种分隔符 {% ... %}
和 {{ ... }}
,前者用于执行诸如 for 循环 或 赋值的语句,后者把表达式的结果打印到模板上
将变量传到到模板后,可以使用 .
来访问变量的属性,作为替代,也可以使用下标语法 []
,下面几行效果是一样的
{{ foo.bar }}
{{ foo['bar'] }}
要把模板中一行的部分注释掉,默认使用 {# ... #}
注释语法
控制结构指的是所有的可以控制程序流的东西 --条件(if/elif/else)、for循环等,控制结构在默认语法中以 {% ... %}
块的形式出现
遍历序列中的每项
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
在一个 for 循环块中你可以访问这些特殊的变量
变量 | 描述 |
---|---|
loop.index |
当前循环迭代的次数 (从 1 开始) |
loop.index0 |
当前循环迭代的次数 (从 0 开始) |
loop.revindex |
到循环结束需要迭代的次数(从 1 开始) |
loop.revindex0 |
到循环结束需要迭代的次数(从 0 开始) |
loop.first |
如果是第一次迭代,为 True |
loop.last |
如果是最后一次迭代,为 True |
loop.length |
序列中的项目数 |
loop.cycle |
在一串序列间期取值的辅助函数。见下面的解释 |
在 for 循环中,可以使用特殊的 loop.cycle
辅助函数,伴随循环在一个字符串 / 变量列表中周期取值
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
与 python 中不同,模板中的循环不能 break 或 continue
{% if a == 1 %}
a == 1
{% elif a == 2 %}
a == 2
{% else %}
a != 1 && a != 2
{% endif %}
Jinja 中最强大的部分就是模板继承,可以把一写公共的代码放在父模块中,避免每个模块写同样的代码。同时父模板中提前在可能更改的地方定义好接口,方便子模板进行修改!
基本的父模板
这个模板,我们习惯性叫做 base.html
,定义了一个简单的 HTML 骨架文档
<html>
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>
{% block title %}{% endblock %} - My Webpage
title>
{% endblock %}
head>
<body>
<div id="content">
{% block content %}{% endblock %}
div>
<div id="footer">
{% block footer %}{% endblock %}
div>
body>
html>
所有的 block 标签告诉模板引擎子模板可以覆盖模板中的这些部分
{% block 接口名 %}
{% endblock %}
子模板
# 继承父模板
{% extends "base.html" %}
# 覆盖父模板 title 块的内容
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome on my awesome homepage.
</p>
{% endblock %}
include 语句用于包含一个模板,并在当前命名空间中返回那个文件的内容渲染结果
<ul>
<li>Pythonli>
<li>Javali>
<li>PHPli>
<li>GOli>
<li>C++li>
ul>
{% include "cs.html" %}
{% include "cs.html" ignore missing %}
一个模板中可以多次使用 include 语句
include 可以和 模板继承同时使用
Jinja2 中文手册