第3章 模板

news2024/9/23 12:23:59

学习目标

  • 了解模板与模板引擎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.3
    li = [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.3
    li = [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,密码是否为123
        if 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.coloradmin.cn/o/1440599.html

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

相关文章

Redis篇之过期淘汰策略

一、数据的过期策略 1.什么是过期策略 Redis对数据设置数据的有效时间&#xff0c;数据过期以后&#xff0c;就需要将数据从内存中删除掉。可以按照不同的规则进行删除&#xff0c;这种删除规则就被称之为数据的删除策略&#xff08;数据过期策略&#xff09;。 2.过期策略-惰…

1.3 Verilog 环境搭建详解教程

学习 Verilog 做仿真时&#xff0c;可选择不同仿真环境。FPGA 开发环境有 Xilinx 公司的 ISE&#xff08;目前已停止更新&#xff09;&#xff0c;VIVADO&#xff1b;因特尔公司的 Quartus II&#xff1b;ASIC 开发环境有 Synopsys 公司的 VCS &#xff1b;很多人也在用 Icarus…

python-自动化篇-办公-一键将word中的表格提取到excel文件中

文章目录 代码 工作中&#xff0c;经常需要将Word文档中的表格粘贴到Excel文件中&#xff0c;以便汇总及分析。一个一个复制粘贴&#xff0c;非常不方便&#xff0c;还是Python自动化操作&#xff0c;省心省力。要求如下图所示&#xff0c;即将word中的所有表格&#xff0c;转存…

Transformer实战-系列教程13:DETR 算法解读

&#x1f6a9;&#x1f6a9;&#x1f6a9;Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 1、物体检测 说到目标检测你能想到什么 faster-rcnn系列&#xff0c;开山之作&…

【开源】SpringBoot框架开发大病保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大病保险管理2.4 大病登记管理2.5 保险审核管理 三、系统详细设计3.1 系统整体配置功能设计3.2 大病人员模块设计3.3 大病保险模块设计3.4 大病登记模块设计3.5 保险审核模块设计 四、…

vscode无法ssh远程连接到服务器:远程主机可能不符合 glibc 和 libstdc++ VS Code 服务器的先决条件

vscode无法ssh远程连接到服务器&#xff1a;远程主机可能不符合 glibc 和 libstdc VS Code 服务器的先决条件 今天vscode自动更新后无法连接到远程服务器了&#xff0c;提示"远程主机可能不符合 glibc 和 libstdc VS Code 服务器的先决条件" 并且命令窗口一直显示&qu…

DFS——迭代加深、双向DFS、IDA*

迭代加深 迭代加深主要用于dfs搜索过程中&#xff0c;某条支路特别深&#xff0c;但是答案在特别浅的地方&#xff0c;也即在另一个分支中&#xff0c;但是按照dfs的原理&#xff0c;我们是将这条支路搜完才去搜另一条支路。所以我们就要及时剪枝&#xff0c;而迭代加深算法则…

ZigBee学习——在官方例程上实现串口通信

Z-Stack版本为3.0.2 IAR版本为10.10.1 文章目录 一、添加头文件二、定义接收缓冲区三、编写Uart初始化函数四、编写串口回调函数五、函数声明六、函数调用七、可能遇到的问题(function “halUartInit“ has no prototype) 以下所有操作都是在APP层进行&#xff0c;也就是这个文…

XGB-6: 单调性约束Monotonic Constraints

在建模问题或项目中&#xff0c;通常情况下&#xff0c;可接受模型的函数形式会以某种方式受到约束。这可能是由于业务考虑&#xff0c;或者由于正在研究的科学问题的类型。在某些情况下&#xff0c;如果对真实关系有非常强烈的先验信念&#xff0c;可以使用约束来提高模型的预…

机器学习 | 深入集成学习的精髓及实战技巧挑战

目录 xgboost算法简介 泰坦尼克号乘客生存预测(实操) lightGBM算法简介 《绝地求生》玩家排名预测(实操) xgboost算法简介 XGBoost全名叫极端梯度提升树&#xff0c;XGBoost是集成学习方法的王牌&#xff0c;在Kaggle数据挖掘比赛中&#xff0c;大部分获胜者用了XGBoost。…

【平衡小车入门】(PID、FreeRTOS、hal库)

本篇博客记录自己复刻的平衡小车 前言一、硬件需求二、最终效果三、整体流程第一步&#xff1a;stm32通过DRV8833电机驱动模块使用PWM驱动直流减速电机第二步&#xff1a;理解PID算法在平衡小车中的应用第三步&#xff1a;PID调参 四、源代码获取 前言 从代码上看&#xff0c;…

安装Pytorch中的torchtext之CUDA版的正确方式

安装Pytorch和torchtext&#xff1a; Previous PyTorch Versions | PyTorch Installing previous versions of PyTorchhttps://pytorch.org/get-started/previous-versions/ 上面的命令如下&#xff1a; pip install torch2.1.2 torchvision0.16.2 torchaudio2.1.2 --index-…

【RPA】智能自动化的未来:AI + RPA

伴随着人工智能&#xff08;AI&#xff09;技术的迅猛进步&#xff0c;机器人流程自动化&#xff08;RPA&#xff09;正在经历一场翻天覆地的变革。AI为RPA注入了新的活力&#xff0c;尤其在处理复杂任务和制定决策方面。通过融合自然语言处理&#xff08;NLP&#xff09;、机器…

【我与Java的成长记】之String类详解

系列文章目录 能看懂文字就能明白系列 C语言笔记传送门 Java笔记传送门 &#x1f31f; 个人主页&#xff1a;古德猫宁- &#x1f308; 信念如阳光&#xff0c;照亮前行的每一步 文章目录 系列文章目录&#x1f308; *信念如阳光&#xff0c;照亮前行的每一步* 前言一、字符串构…

Mongodb启动为Windows服务开机自启动

注意&#xff1a;mongodb的安装目录不应有中文&#xff0c;如果有&#xff0c;服务启动的路径会出现乱码&#xff0c;导致找不到对应的文件 1.安装好mongoDB 2.创建data目录&#xff0c;并在其中创建db目录和log目录 3.在log目录中创建mongodb.log文件 4.打开cmd&#xff08;用…

【网络攻防实验】【北京航空航天大学】【实验一、入侵检测系统(Intrusion Detection System, IDS)实验】

实验一、入侵检测系统实验 1、 虚拟机准备 本次实验使用1台 Kali Linux 虚拟机和1台 Windows XP 虚拟机,虚拟化平台选择 Oracle VM VirtualBox,如下图所示。 2、 Snort环境搭建 实验前,先确保Kali Linux虚拟机能够访问外网,将网络模式设置为“网络地址转换”: 2.1 安装…

计算两个数相除后的余数返回值为浮点型math.fmod(x, y)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 计算两个数相除后的余数 返回值为浮点型 math.fmod(x, y) [太阳]选择题 请问以下代码执行math.fmod()后输出的结果是&#xff1f; import math print("【执行】math.fmod(10, 4)"…

redis特点

一、redis线程模型有哪些&#xff0c;单线程为什么快&#xff1f; 1、IO模型维度的特征 IO模型使用了多路复用器&#xff0c;在linux系统中使用的是EPOLL 类似netty的BOSS,WORKER使用一个EventLoopGroup(threads1) 单线程的Reactor模型&#xff0c;每次循环取socket中的命令…

【数据结构】一篇文章带你学会八大排序

一、排序的概念1. 排序的使用&#xff1a;2. 稳定性&#xff1a;3. 内部排序&#xff1a;4. 外部排序︰5. 排序的用途&#xff1a; 二、排序的原理及实现1. 插入排序1.1 直接插入排序1.1.1 直接插入排序在现实中的应用1.1.2 直接插入排序的思想及个人理解1.1.3 直接插入排序的排…

嵌入式系统中的故障容错和恢复机制有哪些常用的方法和技术?

嵌入式系统是一种在特定应用领域内运行的计算机系统&#xff0c;其对系统可靠性和稳定性有着较高的要求。在嵌入式系统中&#xff0c;故障容错和恢复机制是至关重要的&#xff0c;因为它们能够确保系统在面临故障和异常情况时能够继续正常工作或者快速恢复正常状态。本文将介绍…