第3章 模板

学习目标

  • 了解模板与模板引擎Jinja2,能够复述模板引擎和模板的作用

  • 掌握模板变量的语法,能够在Jinja2模板中定义模板变量

  • 掌握过滤器的使用,能够在Jinja2模板中使用过滤器过滤模板变量保存的数据

  • 掌握选择结构的使用,能够在Jinja2模板中使用选择结构实现分支判断的功能

  • 掌握循环结构的使用,能够通过循环结构对模板中的变量进行遍历

  • 掌握宏的定义,能够通过macro和endmacro定义宏

  • 掌握宏的调用,能够在Jinja2模板文件中灵活调用定义的宏

  • 掌握消息闪现的实现方式,能够通过flash()函数和get_flashed_message()函数实现消息闪现

  • 掌握静态文件的加载方式,能够在Jinja2模板文件中加载静态文件

  • 掌握模板继承机制,能够解决模板文件中的代码冗余问题

虽然我们可以在Flask程序的视图函数中编写HTML代码,但是在实际开发Web项目时,一个完整的页面往往有上百行甚至上千行HTML代码,如果将HTML代码全部写到视图函数中,这样不仅会使项目的代码变得冗余,而且后期也会难以维护。为了规避这种情况,我们通常会将每个页面的HTML代码保存到一个单独的模板文件中,使展示页面的HTML逻辑代码与Python逻辑代码进行分离,实现表现逻辑和业务逻辑分离的效果。本章将针对模板的相关内容进行介绍。

3.1 模板与模板引擎Jinja2

Flask程序的模板是一个文件,它可以生成任何基于文本格式的文件,比如HMTL、XML、CSV等,模板文件的文本格式通常为HTML格式。模板文件中除了包含固定的HTML代码外,还可以包含描述数据如何插入HTML代码的动态内容,这些动态内容往往会按照模板引擎支持的特殊语法来标记为变量。 模板引擎用于识别模板中的特殊语法标记,它会结合请求上下文环境将变量替换为真实的值,生成最终的HTML页面,这个过程称为渲染。

Flask默认使用的模板引擎是Jinja2,Jinja2是一个功能齐全的模板引擎,它除了允许在模板中使用变量之外,还允许在模板中使用过滤器、选择结构、控制结构、宏等,以多种方式控制模板的输出。 需要说明的是,Flask依赖模板引擎Jinja2,它在安装时已经自动安装了Jinja2,因此,我们在Flask程序中可以直接使用Jinja2,无需再另行安装。

1.创建模板

创建模板其实就是创建HTML文件。为了保证Flask程序能够加载到模板文件,我们需要在项目的根目录下新建一个templates文件夹,之后将程序中用到的所有模板文件存放到该文件夹中。 值得一提的是,templates是Flask预先定义好的模板文件夹名称,如果希望使用其他的文件夹名称,则可以在通过代码创建Flask类对象时为template_folder参数传入其他的文件夹名称。

2.使用Jinja2模板引擎渲染模板

为了能够使用Jinja2模板引擎渲染模板,flask库中提供了render_template()函数。

render_template(template_name_or_list, **context)

template_name_or_list:必选参数,表示要加载的模板名称。 **context:可选参数,表示向模板文件传递的参数,以关键字参数的形式进行传递。注意,关键字参数的名称必须与模板文件中的变量名称保持一致。

通过一个案例分步骤演示如何在Flask程序中使用模板。

通过PyCharm工具创建一个Flask程序Chapter03,在Chapter03项目的根目录下新建templates文件夹,在该文件夹下创建模板文件index.html,并在index.html文件中编写HTML代码。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
</head>
<body>{#一级标题#}<h1>Hello Flask!</h1>
</body>
</html>

通过一个案例分步骤演示如何在Flask程序中使用模板。

在Chapter03项目中创建一个app.py文件,并在该文件中先定义一个视图函数, 再在视图函数中渲染模板文件index.html。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)
@app.route('/index')
def index():return render_template('index.html')  # 渲染模板文件index.html
if __name__ == '__main__':app.run()

3.2 模板基础语法

3.2.1 模板变量

模板变量是一种特殊的占位符,它用于标识模板中会动态变化的数据,当模板被渲染时,模板引擎将模板中的变量替换为由视图函数传递的真实数据。

{{ variable }}

上述格式中,variable表示模板变量的名称,变量名称应与视图函数中传递的关键字参数的名称相同。模板变量的命名规则与Python变量的命名规则相同。

通过示例演示如何在模板中使用模板变量。 在app.py文件的视图函数index()中定义一个变量,之后将该变量传入render_template()函数中。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)
@app.route('/index')
def index():name = 'World'return render_template('one.html', name=name)
if __name__ == '__main__':app.run()
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>Hello {{name}}</h1>
</body>
</html>

Jinja2能够识别所有类型的变量,例如,列表、字典和对象等。若变量保存的数据是一个列表,则可以通过索引获取列表中的某个元素;若变量保存的数据是一个字典,则可以通过字典的键获取相应的值;若变量保存的数据是一个对象,则可以通过点字符访问对象中的属性或方法。

{{ info[3] }}                  # info是列表,获取列表中索引为3的数据
{{ info[username] }}    # info是字典,获取字典中键为username的数据
{{ info.items() }}          # info是对象,获取对象调用items()方法返回的数据

3.2.2 过滤器

在Jinja2中,过滤器是用于修改或过滤模板变量值的特殊函数,使用过滤器可以获取更精确的数据。

{{ variable|filter(parameter) }}

variable表示变量的名称,filter(parameter)表示使用的过滤器,其中parameter表示传递给过滤器的参数,变量名称和过滤器之间使用竖线分隔。如果没有任何参数传给过滤器,则括号可以省略。一个模板变量可以使用多个过滤器,多个过滤器之间使用竖线分隔。

1.内置过滤器

Jinja2提供了许多内置过滤器,常用的内置过滤器如下。

过滤器说明
abs()返回给定参数的绝对值
random()返回给定列表中的一个随机元素
safe()将变量值标记为安全,保证渲染时不进行转义
tojson()将给定参数序列化为JSON字符串
escape()用HTML安全序列替换字符串中的字符&、<、>、'和"
length()返回变量值的长度
sort()对变量保存的数据进行排序,该函数内部调用的是Python的sorted()函数
过滤器说明
join()使用指定符号将字符串中的字符进行拼接,默认符号为空字符串
int()将值转换为整数,如果转换不起作用,返回0
float()将值转换为浮点数,如果转换不起作用,返回0.0
capitalize()将变量值的首字母改为大写字母,其余字母改为小写字母
trim()清除变量值前后的空格
upper()将变量值转换为大写字母

通过一个案例分演示内置过滤器的用法。 在app.py文件中,定义视图函数use_of_filters()以及触发该函数的URL规则/filters,在视图函数use_of_filters()中向模板传递不同类型的数据。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)
@app.route('/filters')
def use_of_filters():num = -2.3li = [2, 1, 5, 6, 7, 4, 4]string = 'flask'return render_template('filters.html', num=num, li=li, string=string)
if __name__ == '__main__':app.run()

通过一个案例分演示内置过滤器的用法。 在templates文件夹中新建filters.html文件,在该文件中对定义的模板变量使用过滤器修改或过滤变量值(部分过滤器演示)。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>{#返回变量num的绝对值#}<h4>绝对值:{{ num|abs }}</h4>{#将变量num转换为整型#}<h4>转换为整型:{{ num|int }}</h4>{#返回变量li中随机的一个元素#}<h4>获取随机元素:{{ li|random }}</h4>{#返回变量li的长度#}<h4>获取列表长度:{{ li|length }}</h4><h4>首字母大写,其他字母小写:{{string | capitalize}}</h4><h4>字母全部大写:{{string | upper}}</h4><h4>字符拼接:{{string | join("-")}}</h4>
</body></html>

2.自定义过滤器

内置过滤器可以满足Flask程序的大部分需求,但有些特殊的需求,如反转列表元素,内置过滤器无法满足这个需求,这时可以自定义过滤器实现这个需求。 自定义过滤器实质上是一个Python函数。例如,自定义一个实现反转列表元素的过滤器。

def custom_filters(data):    # 自定义过滤器return data[::-1] 

自定义过滤器需要注册到Flask的过滤器列表中,才可以在模板文件中使用。使用装饰器app.template_filter()可以将自定义过滤器注册到过滤器列表中,template_filter()方法中包含一个可选参数name,该参数表示过滤器的名称,默认值为被装饰的函数名。

使用装饰器app.template_filter()将自定义的过滤器custom_filters()注册到过滤器列表中。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)
@app.route('/filters')
def use_of_filters():num = -2.3li = [2, 1, 5, 6, 7, 4, 4]string = 'flask'return render_template('filters.html', num=num, li=li, string=string)# 自定义过滤器
@app.template_filter()          	# 注册自定义过滤器
def custom_filters(data):        # 自定义过滤器return data[::-1]if __name__ == '__main__':app.run()

自定义过滤器的使用方式与内置过滤器的使用方式相同。例如,在模板文件filters.html的<body>标签中使用自定义过滤器过滤变量li,获取变量li保存的列表进行反转后的数据。

{#将变量li进行反转#}
<h4>列表反转:{{ li|custom_filters }}</h4>

3.2.3 选择结构

Jinja2支持选择结构,选择结构用于判断给定的条件,根据判断的结果执行不同的语句。Jinja2提供了if、elif、else、endif,其中if、elif、else与Python关键字if、elif、else的含义相同,endif用于标识选择结构的末尾。

if、elif、else、endif均使用{% %}进行包裹,其中if和endif可以构建最简单的单分支语句,它们与elif、else搭配可以构建更复杂的多分支语句。需要注意的是,选择结构必须以{% endif %}结尾。

{% if 条件语句1 %}语句1
{% elif 条件语句2 %}语句2
……
{% else %}
语句n
{% endif %}

通过一个评估成绩的案例分步骤演示如何在模板文件中使用选择结构区分不同成绩的评估结果。 首先在app.py文件中定义视图函数以及触发该函数的URL规则,然后在视图函数中向模板传递分数数据。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)@app.route('/query-score/<int:score>')
def query_score(score):return render_template('select_struct.html',score=score)if __name__ == '__main__':app.run()

然后在templates文件夹中新建模板文件select_struct.html,并在该文件中使用选择结构判断变量score的值是否符合给定条件。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
{% if score >= 85 %}优秀
{% elif 75 <= score < 85 %}良好
{% elif 60 <= score < 75 %}中等
{% else %}差
{% endif %}
</body>
</html>

最后通过浏览器访问http://127.0.0.1:5000/query-score/99后页面中显示了选择结构的执行结果。

3.2.4 循环结构

Jinja2除了支持选择结构之外,还支持循环结构,其作用是循环遍历变量中的每个元素,以便在模板文件中使用这些元素。Jinja2中循环结构与Python中的for语句用法相似。

{% for 临时变量 in 变量 %}语句
{% endfor %}

for、endfor均使用{% %}进行包裹,其中for标识循环结构的起始位置,endfor标识循环结构的结束位置,且两者都不能省略。

通过一个展示商品列表的案例分步骤演示如何在模板文件中使用循环结构遍历每个商品。 在app.py文件中定义视图函数goods()以及触发该函数的URL规则/goods,然后在视图函数中向模板传递商品列表。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)
@app.route('/goods')
def goods():goods_name = ['洗碗机','电饭锅','电烤箱','电磁灶','微波炉']return render_template('loop_struct.html', goods_name=goods_name)
if __name__ == '__main__':app.run()

在templates文件夹中新建模板文件loop_struct.html,并在该文件中使用循环结构遍历模板变量goods_name取出每个商品名称。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><ol>{% for good in goods_name %}<li>{{ good }}</li>{% endfor %}</ol>
</body>
</html>

Jinja2还为循环结构提供了一些特殊的变量,通过访问这些特殊的变量达到控制循环的目的。

变量说明
loop.index当前循环的迭代数(从1开始计数)
loop.index0当前循环的迭代数(从0开始计数)
loop.revindex当前反向循环的迭代数(从1开始计数)
loop.revindex0当前反向循环的迭代数(从0开始计数)
loop.first若当前循环为第一次循环,则返回True
loop.last若当前循环为最后一次循环,则返回True
loop.length当前序列包含的元素数量
loop.previtem上一个迭代的数据
loop.nextitem下一个迭代的数据

3.3 宏的定义与调用

3.3.1 宏的定义

模板中的宏与Python函数类似,它可以传递参数,但没有返回值。在定义宏时,通常会将一部分模板代码写到宏中,然后将代码中动态变化的值替换为模板变量,通过参数传递的方式给变量赋值。 模板中的宏以macro标识开始,以endmacro标识结束。

{% macro 宏的名称(参数列表)%}宏内部逻辑代码
{% endmacro %}

参数列表中可以有零个、一个或多个参数,多个参数之间使用逗号进行分隔;宏内部可以嵌套使用前文介绍的过滤器、选择结构、循环结构等。

在macro.html文件的body标签中,定义一个描述input控件类型的宏。

{% macro inputstyle(name, value='', type='checkbox') %}<input name="{{ name }}" value="{{ value }}" type="{{ type }}">
{% endmacro %}

3.3.2 宏的调用

宏定义好之后不会立即执行,直到被程序调用时才会执行,程序调用后之后会返回一个包含HTML代码的字符串或模板。

宏的名称(参数列表)

在项目的templates目录下新建文件macro.html,之后在该文件的body标签中调用定义好的宏inputstyle。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>{% macro inputstyle(name, value='', type='checkbox') %}<input name="{{ name }}" value="{{ value }}" type="{{ type }}">{% endmacro %}<h4>您目前对哪些技术感兴趣?</h4><p>{{ inputstyle('Python') }} Python</p><p>{{ inputstyle('Java') }} Java</p><p>{{ inputstyle('big_data') }} 大数据</p><p>{{ inputstyle('JavaScript') }} JavaScript</p><p>{{ inputstyle('commit', value="提交", type="button") }}</p>
</body>
</html>
from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)@app.route('/macro')
def input_style():return render_template('macro.html')if __name__ == '__main__':app.run()

如果需要在多个模板文件中使用宏,那么可以将定义宏的代码写入到单独的模板文件中,在调用宏的时候只需要从该模板文件中导入定义的宏即可。宏的导入方式与Python模块的导入方式类似,需要使用import或from... import语句导入定义的宏。

{% import '宏文件的路径' [as 宏的别名] %}                
{% from '宏文件的路径' import 宏的名字 [as 宏的别名] %} 

在项目的templates目录下新建文件macro_called.html,在该文件的body标签中导入macro.html中定义的宏inputstyle,并调用宏inputstyle在页面中创建一个复选框。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
</head>
<body>{% from 'macro.html' import inputstyle %}<p>导入宏</p><p>{{ inputstyle('Python') }} Python</p>
</body>
</html>
from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)@app.route('/macro')
def input_style():# return render_template('macro.html')return render_template('macro_called.html')
if __name__ == '__main__':app.run()

3.4 消息闪现

Flask提供了一种良好地向用户反馈信息的方式——消息闪现,消息闪现会在请求完成后记录一条消息,之后在下一次请求向用户提示这条消息。例如,用户在登录页面输入错误的密码后,单击登录按钮才会在页面提示密码错误的消息。 Flask中通过在视图函数中使用flash()函数实现消息闪现的效果,不过flash()函数执行后不会立即在浏览器页面中为用户弹出一条消息,而是需要在模板中通过get_flashed_messages()函数获取消息,并将其显示到页面中。

1.flash()函数

flash()函数通过flask.flash导入使用,用于发送消息。

flash(message, category='message')

message:必选参数,发送闪现的消息。 category:可选参数,消息的类别。该参数支持4种取值,分别是message、error、info和warning,其中message是默认值,表示任何类型的消息;error表示错误的消息;info表示信息消息;warning表示警告消息。

get_flashed_messages()函数是一个全局函数,可在模板的任意位置调用。

get_flashed_messages(with_categories=False , category_filter=())

with_categories:可选参数,表示是否同时返回消息与消息类别,若设置为True,则会以元组形式返回消息和消息类别;若设置为False,则只会返回消息。 category_filter:可选参数,表示只返回与消息类别一致的消息。

flash()函数会将发送的消息存储到session中,因此我们需要在程序中设置secret_key。

通过一个用户登录案例为大家分步骤演示如何在Flask程序中实现消息闪现的功能,即如果用户登录成功则跳转到主页面,并在登录页面上提示“恭喜您登录成功”的消息;如果用户登录失败则在登录页面提示“用户名或密码错误”的消息。 (1)在app.py文件中定义视图函数home_page(),该函数用于判断用户的登录状态。

app.secret_key = 'Your_secret_key&^52@!' # 设置secret_key
@app.route('/home')
def home_page():username = session.get('username')# 判断session是否存储username的数据if 'username' in session:return render_template('home_page.html', username=username)return redirect(url_for('login'))      # 重定向到login页面

(2)在app.py文件中定义视图函数login(),用于获取用户在login页面输入的用户名和密码,如果用户输入了错误的用户名或密码,则通过消息闪现机制反馈给用户,反之将用户名和密码保存到session中,并将页面重定到home页面。

from flask import Flask, render_template
from flask import flash, redirect, session, request, url_for
app = Flask(__name__)
app.secret_key = 'Your_secret_key&^52@!' # 设置secret_key
@app.route('/home')
def home_page():username = session.get('username')# 判断session是否存储username的数据if 'username' in session:return render_template('home_page.html', username=username)return redirect(url_for('login'))      # 重定向到login页面@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':# 判断用户输入的用户名是否为admin,密码是否为123if request.form['username'] != 'admin' or \request.form['password'] != '123':# 发送登录失败的消息flash('用户名或密码错误', category='error')else:session['username'] = request.form['username']session['password'] = request.form['password']# 发送登录成功的消息flash('恭喜您,登录成功', category='info')# 登录成功,页面重定向到home_page页面return redirect(url_for('home_page'))return render_template('login.html')
if __name__ == '__main__':app.run()

(3)在templates文件夹中新建模板文件home_page.html,该模板文件用于展示home页面以及用户登录成功的消息。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>home</title>
</head>
<body><h2>主页</h2>{#调用get_flashed_messages()函数,获取消息类别为info的消息#}{% for message in get_flashed_messages(category_filter = ('info')) %}<span>{{ message }}</span>{% endfor %}<p>欢迎用户:{{ username }}</p>
</body>
</html>

(4)在templates文件夹中新建模板文件login.html,该模板文件用于展示login页面以及登录失败的消息。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>login</title>
</head>
<body>
<h2>用户登录</h2>{% for message in get_flashed_messages(category_filter = ('error')) %}<p class="error" style="color: red;">{{ message }}</p>{% endfor %}<form action="" method=post class="form"><span>用户名:</span><br><input type=text name=username><br><span>密码:</span><br><input type=password name=password><br><p><input type=submit value=登录></p></form>
</body>
</html>

(5)重启开发服务器,通过浏览器访问http://127.0.0.1:5000/login后展示了login页面。在login页面的用户名输入框和密码输入框中分别输入“111”,单击“登录”按钮后页面显示“用户名或密码错误”的消息。

(6)在图3-10中的用户名输入框和密码输入框中再次输入用户名为admin,密码为123,单击“登录”按钮后跳转到home页面,并显示“恭喜您,登录成功”的消息。

3.5 静态文件的加载

在Flask程序中,默认情况下静态文件都存储在与项目文件同级目录的static文件夹中,该文件夹需要由开发人员创建。 为了能够在模板文件中引用静态文件,需要使用url_for()函数解析静态文件的URL,静态文件的URL规则默认为/static/path:filename。url_for()函数需要接收两个参数,第1个参数表示端点名称,默认值为static;第2个参数filename表示静态文件的名称。

url_for('static', filename='test.png')

以上代码解析图片文件flask.png的URL规则为/static/test.png。

1.在模板中引用图片文件

在模板中若要引用图片文件,可以在定义img标签时通过src属性规定显示图像的URL,该URL是调用url_for()函数解析静态文件的URL。

<img src="{{ url_for('static', filename='test.png') }}">

通过一个案例分步骤演示如何在模板中引用图片文件,并将图片呈现到网页中。 (1)在Chapter03项目的根目录下新建一个static文件夹,在static文件夹中导入图片文件flask.png;在templates目录下新建一个模板文件base.html,之后在模板文件base.html中引用图片文件flask.png。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
<!--    {#引用Italics.css #}-->
<!--    <link rel="stylesheet" href="{{ url_for('static', filename='Italics.css') }}">--><title>基模板</title>
</head>
<body><p>Flask-Logo图片</p>{#引用flask.png#}<img src="{{ url_for('static',filename='flask.png') }}"></body>
</html>

(2)在app.py文件中定义视图函数load_staticfile()以及触发该函数的URL规则/static-file,在该函数中渲染模板文件base.html。

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/static-file')
def load_staticfile():return render_template('base.html')
if __name__ == '__main__':app.run()

(3)重启开发服务器,通过浏览器访问http://127.0.0.1:5000/static-file后,可以看到页面上显示的图片。

2.在模板中引用CSS文件

CSS文件主要用于控制网页的版式、颜色、字体大小和格式等。在模板中若要引用CSS文件,可以在定义link标签时通过src属性规定当前模板与CSS文件之间的关系,src属性的值为stylesheet,表示样式表;通过href属性规定被链接文档的URL,该URL是调用url_for()函数解析静态文件的URL。

 <link rel="stylesheet" href="{{ url_for('static',filename='test.css') }}">

通过一个案例分步骤演示如何在模板中引用CSS文件,对网页中文本的样式进行修改。

(1)新建一个CSS文件Italics.css。

p {font-style:italic}

(2)在Chapter03项目的static目录中导入CSS文件Italics.css,之后在模板文件base.html中引用CSS文件Italics.css。

<head><meta charset="UTF-8"><link rel="stylesheet" href="{{ url_for('static',filename='Italics.css') }}">
</head>
……

(3)重启开发服务器,通过浏览器访问http://127.0.0.1:5000/static-file后,可以在页面中看到加载Italics.css文件的效果。

3.6 模板继承

一个Web网站的多个网页中往往包含一些通用内容和样式,例如,导航栏、标题、页脚等,为了避免在多个模板重复编写通用内容和样式的代码,提高代码的重用率,减少开发人员的工作量,Jinja2提供了模板继承机制。 模板继承机制允许开发人员在一个模板中先定义多个页面的通用内容和样式,再以该模板为基础来拓展模板,此时包含通用内容和样式的模板称为基模板,继承基模板的模板称为子模板。

在Jinja2中,模板继承通过block和extends实现,其中block用于标识与继承机制相关的代码块,extends用于指定子模板所继承的基模板。子模板通过继承可以获取基模板中的内容和结构。

{% extends 基模板名称 %}

{% extends %}必须位于子模板的第一行,当模板引擎解析到{% extends %}时,会将基模板中的内容完整的复制到子模板中。

为了能够让子模板便于覆盖或插入内容到基模板中,我们需要在基模板使用block和endblock定义块代码,同时在子模板中通过定义同名的块。

通过一个案例分步骤演示如何在Flask程序中实现模板继承的功能。

(1)将创建的base.html作为基模板,并在该模板文件中添加创建导航栏和页脚的代码。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8">
<!--    {#引用Italics.css #}--><link rel="stylesheet" href="{{ url_for('static', filename='Italics.css') }}"><title>基模板</title>
</head>
<body><p>Flask-Logo图片</p>{#引用flask.png#}<img src="{{ url_for('static',filename='flask.png') }}"><div class="navigation"><p>我是导航栏</p></div><div class="content">{% block content %}<p>基模板中的内容</p>{% endblock %}</div><div class="footer"><p>我是页脚</p></div>
</body>
</html>

 (2)定义一个继承base.html模板的子模板child.html,子模板中的代码如下所示。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>子模板</title>
</head>
<body>{% extends 'base.html' %}{% block content %}<p>我是子模板</p>{{ super() }}{% endblock %}
</body>
</html>

(3)在app.py文件中定义视图函数extends_template(),之后在该函数中依次渲染模板文件base.html和child.html。

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/child')
def extends_template():return render_template('base.html')# return render_template('child.html')
if __name__ == '__main__':app.run()

如果子模板实现了基模板中定义的block,那么子模板block中的代码就会覆盖基模板中的代码,如果想要在子模板中仍然呈现基模板中的内容,那么可以使用super()函数实现。

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/child')
def extends_template():# return render_template('base.html')return render_template('child.html')
if __name__ == '__main__':app.run()

 

3.7 本章小结

本章首先介绍了模板与模板引擎Jinja2,然后介绍了模板的基础语法,包括模板变量、过滤器、选择结构和循环结构,接着介绍了宏的定义与调用,最后介绍了消息闪现、静态文件的加载和模板继承。通过学习本章的内容,希望读者能够掌握模板的使用技巧,为后续开发项目奠定扎实的基础。

3.8 习题

一,填空题

1.Flask程序中的模板文件默认存储在()文件夹中。

2.自定义过滤器需要通过装饰器(),将其注册到过滤器列表中,以便在模板中使用。

3.使用()函数可以加载指定的模板文件。

4.在模板文件中,循环结构使用()标识结束位置。

5.模板中的宏以()标签标识开始位置。

二,判断题

1.Flask程序的模板是文本文件。()

2.在Jinja2中能够使用列表,字段和对象。()

3.模板变量是一种特殊的占位符。()

4.一个模板变量只能使用一个过滤器。()

5.自定义过滤器实质上是Python函数。()

三,选择题

1.下列选项中,用于返回给定列表中一个随机元素的过滤器是()。

A.abs()

B.random()

C.safe()

D.tojson()

2.下列选项中,关于模板中宏的说法错误的是()。

A.宏可以传递多个参数

B.宏可以有返回值

C.宏以endmacro标识结束位置

D.宏可以使用import或from...import语句导入

3.下列选项中,关于flash()函数说法错误的是()。

A.当消息类别为message时,标识任何类型的消息

B.当消息类别为error时,标识错误的消息

C.当消息类别为info时,标识警告消息

D.模板文件中使用get_flashed_messages()函数获取闪现消息

4.下列选项中,关于模板变量的描述说法错误的是()。

A.模板变量的命名规则与Python变量的命名规则相同

B.模板变量需要使用{{}}包裹

C.模板变量是一种特殊占位符

D.模板变量名必须与视图函数中传递的关键字参数名称相同

5.下列选项中,关于模板继承的描述说法错误的是()。

A.模板继承通过block和extends来实现

B.block用于标识与继承机制相关的代码块

C.extends用于指定子模板所继承的基模板

D.extends可以出现在子模板中的任意位置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/672773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1、卷积分类器

用 Kera 创建你的第一个计算机视觉模型。 数据集下载地址:链接:https://pan.quark.cn/s/f9a1428cf6e3 提取码:XJcv 文章目录 欢迎来到计算机视觉!简介卷积分类器训练分类器示例 - 训练一个卷积分类器步骤1 - 加载数据步骤2 - 定义预训练基步骤3 - 附加头步骤4 - 训练结论欢…

分享70个行业PPT,总有一款适合您

分享70个行业PPT&#xff0c;总有一款适合您 70个行业PPT下载链接&#xff1a;https://pan.baidu.com/s/1wGxmwmzssJud4ZQmI4IqFQ?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

vite项目配置根据不同的打包环境使用不同的请求路径VITE_BASE_URL,包括报错解决

vite环境配置可以看官方文档&#xff1a;环境变量和模式 | Vite 官方中文文档 创建环境配置文件 在项目根目录下面创建.env和.env.production文件&#xff0c;.env是开发环境使用的&#xff0c;.env.production是生产环境使用的。 .env文件&#xff1a; # 基本环境 VITE_APP…

PyTorch 2.2 中文官方教程(二)

在 YouTube 上介绍 PyTorch PyTorch 介绍 - YouTube 系列 原文&#xff1a;pytorch.org/tutorials/beginner/introyt.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 介绍 || 张量 || 自动微分 || 构建模型 || TensorBoard 支持 || 训练模型 || 模型理解 作者&a…

数据结构中的时间复杂度和空间复杂度基础

目录 数据结构 数据结构中的基本名词 数据 数据对象 数据元素 数据项 数据类型 数据对象、数据元素和数据项之间的关系 数据结构及分类 逻辑结构 物理结构 算法 算法的特点 算法设计上的要求 算法效率的衡量 时间复杂度 大O渐进表示法 最坏情况和平均情况 常…

R语言学习case10:ggplot基础画图Parallel Coordinate Plot 平行坐标图

step1: 导入ggplot2库文件 library(ggplot2)step2&#xff1a;带入自带的iris数据集 iris <- datasets::irisstep3&#xff1a;查看数据信息 dim(iris)维度为 [150,5] head(iris)查看数据前6行的信息 step4&#xff1a;利用ggplot工具包绘图 plot5 <- ggparcoord(…

Pandas数据预处理之数据标准化-提升机器学习模型性能的关键步骤【第64篇—python:数据预处理】

文章目录 Pandas数据预处理之数据标准化&#xff1a;提升机器学习模型性能的关键步骤1. 数据标准化的重要性2. 使用Pandas进行数据标准化2.1 导入必要的库2.2 读取数据2.3 数据标准化 3. 代码解析4. 进一步优化4.1 最小-最大缩放4.2 自定义标准化方法 5. 处理缺失值和异常值5.1…

HGAME 2024 WEEK 1 :web ezHTTP

题目&#xff1a; 看到这个就知道是文件头伪造 第一想法就是Referer伪造 所以伪造 Referer: vidar.club 然后构造伪造的Referer 然后提示通过那些东西访问页面&#xff0c;User-Agent: 是构造你浏览器访问信息的&#xff0c;所以复制右边那一串替代就好了 然后要求我们从本地…

STM32Cubmax stm32f103zet6 SPI通讯

一、基本概念 SPI 是英语 Serial Peripheral interface 的缩写&#xff0c;顾名思义就是串行外围设备接口。是 Motorola 首先在其 MC68HCXX 系列处理器上定义的。 SPI 接口主要应用在 EEPROM&#xff0c; FLASH&#xff0c;实时时 钟&#xff0c; AD 转换器&#xff0c;还有数…

【Linux系统化学习】文件描述符fd

目录 基础IO预备知识 C语言文件接口 "w"的方式打开&#xff0c;fputs写入 以"a"的方式打开&#xff0c;fputs写入 使用位图传参 系统调用操作文件 open的使用 第一种形式 第二种形式 write() 文件描述符 文件描述符和进程的关系 默认的三个IO流…

C语言:函数递归

创作不易&#xff0c;给个三连吧&#xff01;&#xff01; 一、什么是递归 递归式一种解决问题的方法&#xff0c;在C语言中&#xff0c;递归就是自己调用自己。 递归的思想&#xff1a; 把⼀个⼤型复杂问题层层转化为⼀个与原问题相似&#xff0c;但规模较小的⼦问题来求解…

考研数据结构笔记(2)

线性表 线性表的定义线性表的基本操作lnitList(&L)DestroyList(&L)Listlnsert(&L,i,e)ListDelete(&L,i,&e)LocateElem(L,e)GetElem(L,i)Length(L)PrintList(L)Empty(L)Tips:引用值 小结 根据数据结构的三要素–逻辑结构、数据的运算、存储结构&#xff0c;…

嵌入式学习Day14 C语言 --- 位运算

位运算 注意&#xff1a;符号位也遵循这个规则 一、按位与(&) 运算规则&#xff1a;一假则假 int a 0x33;a & 0x55;0011 00110101 0101 &----------0001 0001 //0x11 二、按位或(|) 运算规则&#xff1a;一真则真 int a 0x33;a |0x55;0011 00110101 0101 |…

Asp .Net Core 集成 NLog

简介 NLog是一个基于.NET平台编写的日志记录类库&#xff0c;它可以在应用程序中添加跟踪调试代码&#xff0c;以便在开发、测试和生产环境中对程序进行监控和故障排除。NLog具有简单、灵活和易于配置的特点&#xff0c;支持在任何一种.NET语言中输出带有上下文的调试诊断信息…

Python 数据分析库之polars使用详解

概要 数据分析是现代应用程序和业务决策的关键组成部分。Python 作为一门强大的编程语言,拥有丰富的数据处理库和工具,其中之一就是 Polars。Polars 是一个现代化的数据操作和分析库,它提供了高性能的数据操作功能,支持链式方法调用,并且兼容 Pandas 和 Arrow 格式。本文…

微信小程序合集更更更之实现仿网易云播放动效

实现效果 写在最后&#x1f352; 源码&#xff0c;关注&#x1f365;苏苏的bug&#xff0c;&#x1f361;苏苏的github&#xff0c;&#x1f36a;苏苏的码云~

鸿蒙开发-UI-组件导航-Tabs

鸿蒙开发-UI-组件 鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 文章目录 一、基本概念 二、导航 1.底部导航 2.顶部导航 3.侧边导航 4.导航栏限制滑动 三、导航栏 1.固定导航栏 2.滚动导航栏 3…

写后台接口,前后台数据对接(vue+springboot)

一、怎么写接口&#xff1f;&#xff1f;&#xff1f; 1.Entity&#xff08;定义一堆属性之类的&#xff09; altins>getter和setter方法 2.Controller 3.Service&#xff08;查询出数据&#xff09; 调用了一个方法 4.Mapper 5.回到service&#xff08;返回数据&#x…

2024年微信公众号链接爬取

通过输入&#xff08;或文件导入&#xff09;公众号名称&#xff0c;即可爬取该公众号所有历史文章。 通过公众号官方网站调用API&#xff0c;打开开发者工具后发现有 打开后发现有搜索结果的fakeid&#xff0c;这是每个公众号的标识。 点击某公众号后出现 这是具体公众号文章…

Windows中如何使用 Anaconda 和 gempy地质建模

GemPy是一个免费开源的Python软件包&#xff0c;主要用于建立三维地质模型。以下是windows下GemPy的安装过程。 一、&#xff08;可选步骤&#xff09;N卡加速 如果使用的是英伟达的RTX显卡&#xff0c;可以去N卡官网下载cuda安装包以启用GPU加速。 首先检查显卡支持的CUDA版…