模板技术templates

一、简介

  • Web程序里访问一个地址,通常会返回一个包含各类信息的HTML页面。

  • 其中,包含变量和运算逻辑的HTML或其他格式的文本,叫做模板。

  • 执行这些变量替换和逻辑计算工作的过程,称为渲染。

  • 默认情况下,Flask会从模块同级的templates目录下寻找模板。

二、应用场景与价值

  • 使用模板的优点:
  1. 动态内容:Flask模板支持将动态数据插入HTML页面,从而创建个性化和交互式的Web应用程序。

  2. 代码重用:模板允许开发人员在多个页面之间重用常见的HTML组件,减少冗余代码,提高可维护性。

  3. 一致的设计:通过使用模板,开发人员可以确保应用程序在设计和布局上保持一致,从而实现专业和统一的用户体验。

  4. 与其他技术的集成:Flask模板可以轻松与其他前端基础(如CSS框架和JavaScript库)集成,实现现代化和视觉冲击的Web界面。

三、模板渲染

  1. 在项目中创建模板的目录,注意模板的目录名称为templates

  2. templates目录中创建HTML文件,创建完成后,目录结构为:

./
├── xx.py
└── templates
    └── hogwarts.html

  1. 在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>
</head>
<body>
    <h2>这是模板渲染的HTML页面</h2>
</body>
</html>
  1. 视图函数的返回使用render_template()渲染对应的HTML文件:
from flask import Flask, render_template

# 创建Flask应用程序实例
app = Flask(__name__)


@app.route('/')
def html_res():
    return render_template("demo.html")


# 运行应用程序
if __name__ == '__main__':
    app.run()
  1. 启动服务,访问默认地址,即可看到渲染后的HTML页面。

四、模板语法

  • 利用Jinja2模板引擎,可以讲一部分的程序逻辑放到模板中处理。即在模板中使用python语句和表达式来操作数据的输出。

  • 但需要注意,Jinja2并不支持所有python语法。出于效率和代码组织等方面的考虑,应该适度使用模板,仅把和输出控制有关的逻辑操作放到模板中。

  • Jinja2允许在模板中使用大部分python对象,如字符串、列表、字典、元组、整型、浮点型、布尔值。

  • 它支持基本的运算符号+、-、*、/ 等,比较符号==、!=,逻辑符号and、or、not和括号,以及in、is、None和布尔值True、False。

    • 变量代码块{{ }}:主要用于变量的内容显示。

    • 控制代码块{% %}:主要用于涉及到与逻辑相关的代码块展示。

4.1 传递数据

  • 在调用render_template()方法时,可以使用关键字传参的方式,给模板数据传递数据。
  1. 在HTML的body标签中添加{{ 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>模板渲染</title>
</head>
<body>
    <h2>这是模板渲染的HTML页面</h2>
    <h3>{{ name }}</h3>
</body>
</html>
  1. 视图函数中调用方法render_template("demo.html", name="cccy")时,通过关键字传参的方式,将变量name的值传入。
from flask import Flask, render_template

# 创建Flask应用程序实例
app = Flask(__name__)


@app.route('/')
def html_res():
    return render_template("demo.html", name="cccy")


# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)

  1. 启动服务,访问路由,name变量会展示传入的值。

4.2 判断语法

  • Flask中的Jinja2模板提供了多种控制结构,通过这些控制结构可以改变模板的渲染过程。以下为条件控制语句:
<!-- if 条件判断 -->
{% if 条件表达式 %}
......
{% elif 条件表达式 %}
......
{% else %}
......
{% endif %}

示例:

from flask import Flask, render_template

# 创建Flask应用程序实例
app = Flask(__name__)


@app.route('/person/')
def person():
    person = {
        "name": "Cathelin",
        "age": 20,
        "gender": "female"
    }
    return render_template("person.html", person=person)


# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)

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>Person</title>
</head>
<body>
    <p>
        您好:
        {% if person.gender == "male" %}
            {{ person.name }} 先生
        {% else %}
            {{ person.name }} 女士
        {% endif %}
    </p>
</body>
</html>
  • 在模板中,Jinja2支持使用.获取变量的属性,如person字典中的gender键值通过.获取,即person.gender,在效果上等同于person["gender"]

4.3 循环语法

  • 和python一样,for语句用来迭代一个序列。
<!-- for 循环 -->
{% for row in list_or_dict %}
{{ row }}
{% endfor %}

示例:

from flask import Flask, render_template

# 创建Flask应用程序实例
app = Flask(__name__)


@app.route('/people/')
def people():
    people = [
        {
            "name": "Cathelin",
            "age": 20,
            "gender": "female"
        },
        {
            "name": "Mike",
            "age": 23,
            "gender": "male"
        }
    ]
    return render_template("people.html", people=people)


# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)

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>People</title>
</head>
<body>
    {% for p in people %}
    <p>
        您好:
        {% if p.gender == "male" %}
            {{ p.name }} 先生 <br />
        {% else %}
            {{ p.name }} 女士 <br />
        {% endif %}
        您的年龄是 {{ p.age }},<br />
        您的性别是 {{ p.gender }}。<br />
    </p>
    {% endfor %}
</body>
</html>
<script type="text/javascript"></script>

启动服务,访问 /people 路由,页面中会展示列表中所有的人员信息,并且通过判断性别来展示对应的欢迎信息。

4.4 继承语法

  • 模板继承允许创建一个基础的骨架模板,这个模板包含网站的通用元素,并且定义子模板可以重载的区域。

  • 一般在前端页面中有很多页面中有很多相同的地方,比如页面顶部的导航栏,底部的页脚等部分,这时如果每一个页面都重写一遍,会很麻烦,而且也没必要。

  • 这时候就可以做个父模板,里面放上页面中相同的部分,不同的部分先使用其他东西占位。然后在不同的页面中,继承这个父模板,不同的部分填充不同的内容。

4.4.1 定义父模板

<!-- 父模板中定义,字模板可以直接继承重写 -->
{% block 自定义名称 %}
{% endblock %}
  • 标签block用于在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。父模板中也可以使用上下文传递过来的数据。

4.4.2 子模板继承父模板

{% extends '父模板' %}

示例:

  1. 创建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 %} &copy; Copyright 2023 by
        <a href="https://ceshiren.com">测试人社区</a>{% endblock %}
    </div>
</body>
</html>
<script type="text/javascript"></script>
  1. 创建son.html文件,作为子模板,用来继承父模板;这里对title、content进行了定制;

<!-- son.html -->

{% extends "layout.html" %}

{% block title %} Son Page {% endblock %}

{% block content %}

<h1>子模板</h1>
<button>确认</button>

{% endblock %}
  1. 定义视图函数,返回子模板HTML文件;

  1. 访问路由,展示HTML页面。

4.5 模板导入

  • 模板导入就是将另一个模板加载到当前模板中,直接渲染。

  • 模板继承和类的继承含义是一样的,主要是为了提高代码重用,减轻开发工作量。

4.5.1 导入语法

{% include "文件名" %}

示例:

  1. 创建顶部栏页面top.html;
<a>首页</a>
<a>查询</a>
<a>关于</a>
  1. 在son.html中导入top.html;
<!-- son.html -->

{% extends "layout.html" %}

{% block title %} Son Page {% endblock %}

{% include "top.html" %}

{% block content %}

<h1>子模板</h1>
<button>确认</button>

{% endblock %}
  1. 该模板直接加载并渲染到当前模块中。

4.5.2 导入列表

  • 可以导入一个模板列表,程序会按照顺序依次寻找模板文件,第一个被找到的模板将被加载和渲染,后续的忽略。
{% include ["footer.html", "bottom.html", "top.html"] %}
  1. 如果找不到模板,程序就会报错;


  1. 第一个被找到的模板将被加载和渲染。


image

4.5.3 忽略报错

  • include语句后面添加ignore missing就可以忽略报错。
{% include ["footer.html", "bottom.html", "top.html"] ignore missing %}

image