模版技术
今天我们讲的主题是Flask中的模板技术,它是用来构建动态网页的一个重要工具。简单来说,模板让我们能够把静态的HTML和动态的数据结合在一起,使得页面可以根据不同的输入动态展示内容。
简介
Web 程序里,访问一个地址通常会返回一个包含各类信息的 HTML 页面。其中包含变量和运算逻辑的 HTML 或其他格式的文本叫做模板,执行这些变量替换和逻辑计算工作的过程被称为渲染。Flask 模板渲染是通过 Jinja2 引擎来完成的。
默认情况下,Flask 会从模块同级的 templates
目录下寻找模版。
在Web程序中,当你访问一个地址时,服务器会返回一个HTML页面,这个页面通常包含了静态和动态的内容。这里提到的模板就是一种包含动态内容的HTML文件,它能根据不同的数据进行渲染。Flask框架使用Jinja2引擎来渲染这些模板。默认情况下,Flask会在templates这个文件夹里查找模板。
应用场景与价值
使用模版的优点为:
- 动态内容:Flask 模板支持将动态数据插入 HTML 页面,从而可以创建个性化和交互式的 Web 应用程序。
- 代码重用:模板允许开发人员在多个页面之间重用常见的 HTML 组件,减少冗余代码,提高可维护性。
- 一致的设计:通过使用模板,开发人员可以确保应用程序在设计和布局上保持一致,从而实现专业和统一的用户体验。
- 与其他技术的集成:Flask 模板可以轻松与其他前端技术(如 CSS 框架和 JavaScript 库)集成,实现现代化和视觉上吸引人的 Web 界面。
那么,为什么要使用模板呢?主要有几个优点。首先,模板可以让你轻松地将动态内容插入到HTML中,创造个性化的用户体验。第二,模板帮助我们重用代码,这样你就可以在多个页面间共享HTML结构,而不需要重复编写相同的内容,提升了代码的可维护性。第三,通过模板,能够保证整个Web应用在设计和布局上的一致性。最后,模板非常适合与CSS和JavaScript等前端技术结合使用,能够帮助我们构建现代化、吸引人的界面。
模版渲染
- 在项目中创建模板的目录,注意模板的目录名称为
templates
。 - 在
templates
目录中创建 HTML 文件,创建完成之后,目录结构为:./ ├── xx.py └── templates └── hogwarts.html
当你在Flask中使用模板时,首先要做的就是创建一个存放模板的目录,默认是templates。然后在这个目录下创建你的HTML文件。比如我们可以在项目中创建一个hogwarts.html文件。目录结构可能是这样的。
- 在
hogwarts.html
文件中写入以下内容:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Hogwarts</title> </head> <body> <h1>霍格沃兹平台</h1> </body> </html> <script type="text/javascript"></script>
接下来,我们可以在hogwarts.html中写一些HTML代码,这个页面将会展示“霍格沃兹平台”的信息。
-
视图函数的返回使用
render_template()
渲染对应的 HTML 文件,代码如下:from flask import Flask, render_template # 创建 Flask 应用程序实例 app = Flask(__name__) @app.route("/") def hello(): return render_template("hogwarts.html") # 运行应用程序 if __name__ == '__main__': app.run(port=5055, debug=True)
然后视图函数的返回使用 render_template()
渲染对应的 HTML 文件。
- 启动服务,访问默认地址,即可看到渲染的 HTML 页面。
启动服务,访问默认地址,就能看到渲染的 HTML 页面了。
模版语法
利用 Jinja2 模板引擎,可以将一部分的程序逻辑放到模板中处理。也就是可以在模板中使用 python 语句和表达式来操作数据的输出。但需要注意的是,Jinja2 并不支持所有 python 语法。并且出于效率和代码组织等方面的考虑,应该适度使用模板,仅把和输出控制有关的逻辑操作放到模板中。
Jinja2 允许在模板中使用大部分 python 对象,比如字符串、列表、字典、元组、整型、浮点型、布尔值。它支持基本的运算符号(+、-、\*、/
等)、比较符号(比如==、!=
等)、逻辑符号(and、or、not 和括号)以及 in、is、None 和布尔值(True、False)。
- 变量代码块
{{ }}
: 主要用于变量的内容显示。 - 控制代码块
{% %}
: 主要用于涉及到与逻辑相关的代码块展示。
Jinja2模板引擎让你能够在模板中嵌入Python语法,这样我们就可以在模板中动态处理数据。不过,Jinja2并不是支持所有Python语法的,它主要是支持一些基本的操作,比如数学运算、字符串操作、列表或字典的访问等。Jinja2模板中有两种常见的语法块:一个是变量块{{ }}
,用来显示数据,另一个是控制块{% %}
,用来写逻辑判断或者循环。
传递数据
在调用 render_template()
方法的时候,可以使用关键字传参的方式,给模板数据传递数据。
你可以通过render_template()方法将数据传递到模板中,这样模板就能够渲染不同的内容。
- 在
hogwarts.html
的 body 标签中添加如下的 html 代码,其中{{ name }}
代表模版中所包含的变量信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hogwarts</title>
</head>
<body>
<h1>霍格沃兹平台</h1>
<h2>{{ name }}</h2>
</body>
</html>
<script type="text/javascript"></script>
举个例子,我们在hogwarts.html模板中的<h2>{{ name }}</h2>
部分,name是一个变量,它的值会根据我们在视图函数中传递的数据而变化。
- 视图函数中调用方法
render_template('hogwarts.html, name='hogwarts')
的时候,通过关键字传参的方式,将变量 name 的值传入进去。
from flask import Flask, render_template
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route("/data")
def hogwarts():
return render_template("hogwarts.html", name="hogwarts")
# 运行应用程序
if __name__ == '__main__':
app.run(port=5055, debug=True)
比如我们在视图函数中传递了name="hogwarts",模板中就会显示hogwarts。
- 启动服务,访问
/data
路由,name 变量的位置会展示的传入的值,也就是 hogwarts。
通过这种方式,你可以动态更新页面内容。
判断语法
Flask 中的 Jinja2 模板提供了多种控制结构,通过这些控制结构可以改变模板的渲染过程。以下为条件控制语句。
<!-- if 条件判断-->
{% if 条件表达式 %}
.......
{% elif 条件表达式 %}
.......
{% else %}
.......
{% endif %}
Jinja2还支持条件判断语句,让你可以根据不同的数据执行不同的操作。例如,我们可以通过if语句判断一个人的性别,来决定显示“女士”还是“先生”。这样就可以根据数据动态调整页面的显示内容。在实际开发中,这种控制结构非常有用,它可以帮助我们根据用户的输入或其他动态因素改变网页内容。
示例:
from flask import Flask, render_template
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route("/person")
def person():
person = {
"name": "lily",
"age": 18,
"gender": "female"
}
return render_template("person.html", person=person)
# 运行应用程序
if __name__ == '__main__':
app.run(port=5055, debug=True)
{.hidden .audio .subtitle}
templates 目录下创建 person.html 文件。
<!-- person.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
</head>
<body>
<p>
您好,
{% if person.gender == "male" %}
{{ person.name }} 先生
{% else %}
{{ person.name }} 女士
{% endif %}
</p>
</body>
</html>
<script type="text/javascript"></script>
{.hidden .audio .subtitle}
在模板中,Jinja2 支持使用 .
获取变量的属性,比如 person 字典中的 gender 键值通过 .
获取,即 person.gender
,在效果上等同于 person['gender']
。
启动服务,访问 /person
路由,可以通过判断性别来展示对应的欢迎信息。
{.hidden .audio .subtitle}
循环语法
和 python 里一样,for 语句用来迭代一个序列。
<!-- for 循环 -->
{% for row in list_or_dict %}
{{ row }}
{% endfor %}
除了条件判断,Jinja2还支持循环语句,你可以用它来遍历列表、字典等数据结构。例如,如果你有一组人员数据,可以通过for循环来渲染每个人的信息。这样,我们就可以动态生成一个包含多个元素的列表或表格。
示例:
from flask import Flask, render_template
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route("/people")
def people():
people = [
{
"name": "lily",
"age": 18,
"gender": "female"
},
{
"name": "tom",
"age": 19,
"gender": "male"
},
]
return render_template("people.html", people=people)
# 运行应用程序
if __name__ == '__main__':
app.run(port=5055, debug=True)
{.hidden .audio .subtitle}
templates 目录下创建 people.html 文件。
<!-- people.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
</head>
<body>
{% for p in people %}
<p>
Hello,
{% if p.gender == "male" %}
Mr. {{ p.name }}
{% else %}
Ms. {{ p.name }}<br />
{% endif %}
Your age is {{ p.age }}<br />
Your gender is {{ p.gender }}<br />
</p>
{% endfor %}
</body>
</html>
<script type="text/javascript"></script>
{.hidden .audio .subtitle}
启动服务,访问 /people
路由,页面中会展示列表中所有的人员信息,并且通过判断性别来展示对应的欢迎信息。
{.hidden .audio .subtitle}
继承语法
模板继承允许创建一个基础的骨架模板, 这个模板包含网站的通用元素,并且定义子模板可以重载的区域。
一般在前端页面中有很多页面中有很多相同的地方,比如页面顶部的导航栏,底部的页脚等部分,这时候如果每一个页面都重写一遍,会很麻烦,而且也没必要。
这时候就可以做一个模板,叫做父模板,里面放上页面中相同的部分,不同的部分先使用其他东西占位。然后在不同的页面中,继承这个父模板,不同的部分填充不同的内容。
模板继承允许你创建一个基础模板,把网站的通用部分,比如导航栏、页脚等写在一个父模板里,然后在子模板中继承这个父模板并填充不同的内容。这样,你就能避免在每个页面中重复相同的内容,提升了代码的复用性。父模板中定义了一个{% block %}
区域,子模板可以通过{% extends %}
来继承,并且用{% block %}
填充不同的内容。这样,你就可以将页面的共同部分抽象成父模板,专注于具体页面的个性化内容。
-
定义父模板
<!-- 父模版中定义,子模板可以直接继承重写 --> {% block 自定义名称 %} {% endblock %}
标签 block 用于在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。父模板中也可以使用上下文中传递过来的数据。
-
子模板继承父模版
{% extends '父模版' %}
{.hidden .audio .subtitle}
示例
layout.html
文件是父模板,也可以看成是一个骨架。这个父模版可以让继承者对 title、content、footer 三个地方进行定制。
<!-- layout.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %} © Copyright 2023 by
<a href="https://ceshiren.com">测试人社区</a>. {% endblock %}
</div>
</body>
</html>
<script type="text/javascript"></script>
{.hidden .audio .subtitle}
son.html
文件是子模版,是用来继承父模板的。子模版继承了父模板,并对 title、content 进行定制。
<!-- son.html -->
{% extends "layout.html" %}
{% block title %}Son Page{% endblock %}
{% block content %}
<h1>子模版</h1>
<button>按钮</button>
{% endblock %}
{.hidden .audio .subtitle}
- 定义视图函数,返回子模版 HTML 文件:
from flask import Flask, render_template
# 创建 Flask 应用程序实例
app = Flask(__name__)
@app.route("/extend")
def extend():
return render_template("son.html")
# 运行应用程序
if __name__ == '__main__':
app.run(port=5055, debug=True)
{.hidden .audio .subtitle}
- 访问路由后,展示页面如下所示:
{.hidden .audio .subtitle}
模版导入
模板导入就是将另一个模板加载到当前模板中,直接渲染。模板继承和类的继承含义是一样的,主要是为了提高代码重用,减轻开发工作量。
导入语法
{% include '文件名' %}
除了继承,你还可以在模板中直接导入其他模板。这类似于类的继承,它的目的是为了提高代码的复用性。你可以通过{% include '文件名' %}来导入其他模板,并且把它渲染到当前模板中。这种方法特别适合页面中有多个公共部分,比如顶部导航栏、底部信息等,可以通过include将它们加载进来,减少重复代码的编写。
示例
- 创建顶部栏页面 top.html
<a>首页</a>
<a>关于</a>
{.hidden .audio .subtitle}
- 在 son.html 中导入 top.html
{% extends "layout.html" %}
{% block title %}Son Page{% endblock %}
{% include "top.html" %}
{% block content %}
<h1>子模版</h1>
<button>按钮</button>
{% endblock %}
{.hidden .audio .subtitle}
- 导入 top.html,该模版直接加载并渲染到当前模块中。
{.hidden .audio .subtitle}
- 导入列表
也可以导入一个模板列表,程序会按照顺序依次寻找模板文件,第一个被找到的模板将被加载和渲染,后续的忽略。
{% include ['footer.html','bottom.html','top.html'] %}
{.hidden .audio .subtitle}
- 忽略报错
此时,如果都没找到,程序会报错,如果想要忽略报错,可以在后面添加ignore missing
,用来忽略include
语句。
{% include ['footer.html','bottom.html','end.html'] ignore missing %}
{.hidden .audio .subtitle}
总结
- 模版渲染
- 模版语法
今天我们讲解了Flask模板技术的几个核心概念,包括模板渲染、语法、条件判断、循环、模板继承和模板导入。模板技术是Web开发中的一项重要技术,它帮助我们将动态数据和静态页面结合起来,提升了代码的复用性和可维护性。希望通过今天的讲解,大家能对Flask模板的使用有一个更清晰的了解。