当前位置:   article > 正文

篇二、Flask中默认集成了Jinja2,用于web应用程序中生成动态内容。进阶篇_jinja2表格动态生成

jinja2表格动态生成

⭐ 简介:大家好,我是zy阿二,我是一名对知识充满渴望的自由职业者。
☘️ 最近我沉溺于Python的学习中。你所看到的是我的学习笔记。
❤️ 如果对你有帮助,请关注、点赞,让我们共同进步。有不足之处请留言指正!

1. Flask打造 Python Web 开发的灵活框架,实现简易登录。入门篇

2. Flask中默认集成了Jinja2,用于web应用程序中生成动态内容。进阶篇【本文】

# 前言

Jinja2是一个流行的HTML引擎,用于在Flask等Python Web应用程序中生成HTML,XML或其他文本格式的动态内容。Flask中默认集成了Jinja2。

Jinja2允许开发人员将动态内容与静态HTML代码分离。通过在HTML中使用Jinja2语法,可以将动态内容以一种可读性强且易于维护的方式与HTML混合在一起。Jinja2还支持过滤器,控制结构和继承等高级功能。

Flask中,可以通过将Jinja2模板存储在应用程序的“templates”目录中,并使用Flask的内置render_template函数将模板渲染为响应发送给客户端。例如,在Flask应用程序中渲染一个名为“index.html”的模板的代码如下:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html', name='World')

if __name__ == '__main__':
    app.run()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在此示例中,应用程序使用render_template函数渲染了“index.html”,并将参数“name”设置为“World”。在模板中,可以使用Jinja2语法来访问该参数,例如:

<!DOCTYPE html>
<html>
<head>
	{# 我是注释 #}
    <title>Hello {{ name }}!</title>
</head>
<body>
	{# 我是注释 #}
    <h1>Hello {{ name }}!</h1>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这个例子中

  • 使用{{ name }}语法来引用传递给它的参数“name”,从实现不同用户显示不同的HTML内容。(即:动态HTML内容)
  • 同时{# 我是注释 #}是Jinja2注释的格式。



1. Jinja2的for循环示例

当我们想要根据列表、字典或其他可迭代对象在HTML上生成一个列表时,我们就可以这样做。

下面我们创建了一个名为 "my_list.html " 的文件,并写入内容如下:

<!DOCTYPE html>
<html>
<head>
    <title>My List</title>
</head>
<body>
    <h1>My List</h1>
    <ul>
        {% for item in my_list %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

假设一个名为 “my_list” 的Python列表,在模板中使用for循环来遍历这个列表,并使用{{ item }}在每个项目之前创建一个HTML列表项。

为了在Flask应用程序中使用此模板,我们可以使用"render_template"函数并将"my_list"作为参数传递给模板。例如:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    my_list = ['item 1', 'item 2', 'item 3']
    return render_template('my_list.html', my_list=my_list)

if __name__ == '__main__':
    app.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行并打开后将得到如下页面:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z9xnvGLo-1677990858750)(C:\Users\张义\AppData\Roaming\Typora\typora-user-images\image-20230305122742840.png)]

当然,我们可以通过修改 ”my_list“ 中的内容来实现更加丰富的动态页面。

值得注意的是 :

  1. {{ item }}在Jinja2中引用变量需要2个花括号包裹。如需引用多个,每一个变量都需要2个花括号包裹。例如{{ item1 }}{{ item2 }}

  2. for循环也有严格的格式{% for ... in .... %}而且{% endfor %}也是必须的。表示for循环代码结束的位置,循环的内容则写在中间。

  3. Jinja2的for循环是直接完成的,它不同于Python还有break方法来提前中断循环。

      {% for item in my_list %}
          <li>{{ item }}</li>
      {% endfor %}
  • 1
  • 2
  • 3


2. Jinja2的for循环生成表格示例

假设 my_list 是一个二维数组,每个值中包含,书名,作者,价格和日期。根据my_list 生成一个带有表格的HTML页面。

“my_list.html” 文件内容如下:

<!DOCTYPE html>
<html>
<head>
    <title>Book List</title>
    <!-- 为了使得表格看上去美观一点,我引入了bootstrap。虽然可以使用原生CSS美化,但是会让代码变得太长,不适合演示。不懂bootstrap的可以选择性的屏蔽掉所有的class 或者直接删除下方的link标签-->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <h1>Book List</h1>
        <table class="table table-bordered table-striped">
            <thead class="thead-dark">
                <tr>
                    <th scope="col">Book</th>
                    <th scope="col">Author</th>
                    <th scope="col">Price</th>
                    <th scope="col">Date</th>
                </tr>
            </thead>
            <tbody>
                {% for row in my_list %}
                    <tr>
                        <td>{{ row[0] }}</td>
                        <td>{{ row[1] }}</td>
                        <td>{{ row[2] }}</td>
                        <td>{{ row[3] }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

py文件内容如下:

from flask import Flask, render_template

app = Flask(__name__)

# 运行代码后访问:  `http://localhost:5000` 
@app.route('/')
def index():
    my_list = [['Book 1', 'Author 1', 19.99, '2020-01-01'],
        ['Book 2', 'Author 2', 29.99, '2021-02-02'],
        ['Book 3', 'Author 3', 39.99, '2022-03-03'],
        ['Book 4', 'Author 4', 49.99, '2023-04-04'],
        ['Book 5', 'Author 5', 59.99, '2024-05-05']]
    return render_template('my_list.html', my_list=my_list)

if __name__ == '__main__':
    app.run()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

运行代码后访问: http://localhost:5000 ,得到如下页面:
在这里插入图片描述

3. Jinja2的if 判断

  • if语句的语法结构:
    {% if .... %}

    {% elif ... %}

    {% endif %}
  • 值得注意的还是{%..%}的结构和必须在if结束的位置加上{% endif %}
  • 延用上一条中的书本Book List的py数据。
    这次我们在循环内加上了if语句做条件判断,如果价格小于20,就给这一行加上黄色背景,如果价格大于40,就给这一行加上红色背景,否则就不加背景。这里的row[2]就是价格,row[0]是书名,row[1]是作者,row[3]是日期。
<!DOCTYPE html>
<html>

<head>
    <title>Book List</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        <h1>Book List</h1>
        <div class="table-responsive">
            <table class="table table-hover">
                <thead class="thead-light">
                    <tr>
                        <th scope="col">Book</th>
                        <th scope="col">Author</th>
                        <th scope="col">Price</th>
                        <th scope="col">Date</th>
                    </tr>
                </thead>
                <tbody>
                    {% for row in my_list %}
                    <!-- 这次我们在循环内加上了if语句做条件判断,如果价格小于20,就给这一行加上黄色背景,如果价格大于40,就给这一行加上红色背景,否则就不加背景。这里的row[2]就是价格,row[0]是书名,row[1]是作者,row[3]是日期。 -->
                    {% if row[2] < 20 %} <tr style="background-color: yellow;">
                        {% elif row[2] > 40 %}
                        <tr style="background-color: red;">
                            {% else %}
                        <tr>
                            {% endif %}
                            <td>{{ row[0] }}</td>
                            <td>{{ row[1] }}</td>
                            <td>{{ row[2] }}</td>
                            <td>{{ row[3] }}</td>
                        </tr>
                        {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

执行代码后,访问: http://localhost:5000 得到如下页面
在这里插入图片描述



3. if判断简单示例

首先创建一个“index.html” 写入代码:

<!DOCTYPE html>
<html>

<head>
    <title>{{ title }}</title>
</head>

<body>
    {% if user %}
    <h1>欢迎你, {{ user.username }}!</h1>
    {% else %}
    <h1>欢迎来宾!</h1>
    {% endif %}
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在上面的html文件中,使用双花括号“{{}}”插入变量和使用“{% %}”控制流,如果有user,则显示欢迎用户的消息,否则显示欢迎来宾的消息。其中,user和title是在Flask应用程序中定义的变量。

然后在py文件中写入:

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    user = {'username': 'John'}
    return render_template('index.html', title='Home', user=user)


if __name__ == "__main__":
    app.run(debug=True)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5. Jinja2的 extends

  • 语法结构:
    {% block name %} ... {% endblock %}

{% block %} 是 Jinja2 模板引擎的一个核心功能,它允许您定义一个模板块,该模板块可以在子模板中被重写和填充。类似python中的class封装一些固定的方法,减少代码的重用率。

具体来说,{% block %} 标记定义了一个命名的模板块,可以将该模板块视为一个占位符。在父模板中,该模板块可能包含一些默认内容,但是在子模板中,该模板块可以被重写,并且将显示子模板中的新内容。以下是一个简单的示例:

首先创建一个base.html 模版:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %} base.html 模版的title {% endblock %}</title>
</head>
<body>
    <div class="header">
        {% block header %} base.html 模版的 Header{% endblock %}
    </div>
    <div class="content">
        {% block content %} base.html 模版的 Content{% endblock %}
    </div>
    <div class="footer">
        {% block footer %} base.html 模版的 Footer{% endblock %}
    </div>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

再创建一个home.html 模版:

{% extends 'base.html' %}

{% block title %}
主页
{% endblock %}

{% block header %}
<h1>欢迎来到我的主页</h1>
{% endblock %}

{% block content %}
<p>我是一个有理想有目标有远见有卓越智慧的肉肉!!</p>
{% endblock %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

home.html 模板中,我们继承了 base.html 模板,并重写了 titleheadercontent 中的内容,以创建一个和 base.html 结构相同但是内容却不一样的主页。就像是python中创建一个类,继承另一个类,又重写了父类方法。

再创建一个about.html 模板:

{% extends 'base.html' %}

{% block title %}
关于我
{% endblock %}

{% block header %}
<h1>我的简介</h1>
{% endblock %}

{% block content %}
<p>我是一盒坚持学习不断进取的猪肉!!</p>
{% endblock %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

新的about.html 模板,我们又继承了 base.html 模板,并再次重写了 titleheadercontent 中的内容,所以这3个模版的HTML结构都是相同的,但是其中的内容是不同的。

最后,我们创建一个py文件,代码如下:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('home.html')

@app.route('/about')
def about():
    return render_template('about.html')

if __name__ == '__main__':
    app.run(debug=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

运行,然后访问 http://localhost:5000http://localhost:5000/about,以查看生成的 HTML 页面。
在这里插入图片描述在这里插入图片描述
最后你可以自己尝试重新修改以下“ base.html 模版的 Footer ”的内容。

总结: {% block name %} ... {% endblock %}的目的就是为了减少代码的重用率。

6. Jinja2的 macro name(args)

  • 既然有类就有函数。语法结构:
  • {% macro macro(args) %}{% endmacro %} 定义一个函数

定义一个可重用的模板块,称为“宏”(Macro)。 它类似于一个函数,接受一个或多个参数,可以在模板中多次调用,以避免重复编写相同的代码。宏可以带有参数,这些参数可以在宏内部使用,用于生成特定的输出。类是于python中的 def macro(*arg): 在函数内部执行完成后通过return输出结果。

例如,以下代码定义了一个名为 hello 的宏,它带有一个参数 name,并在模板中使用了调用了他3次:

    {% macro hello(name) %}
    <h1>你好我好大家好,我是 {{ name }}!</h1>
    {% endmacro %}

    {{ hello('John') }}
    {{ hello('Binbin') }}
    {{ hello('Liya') }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

下面是一个完整的 Flask 和 Jinja2 模板的示例。

首先创建一个“index.html” 写入代码:

<!DOCTYPE html>
<html>

<head>
    <title>Hello World</title>
</head>
<body>
    {% macro hello(name) %}
    <h1>你好我好大家好,我是 {{ name }}!</h1>
    {% endmacro %}
    {{ hello('John') }}
    {{ hello('Binbin') }}
    {{ hello('Liya') }}
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

py文件代码如下:

from flask import Flask, render_template
from jinja2 import Template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == "__main__":
    app.run(debug=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

执行代码后,访问 http://localhost:5000 后得到如下页面:
在这里插入图片描述
在这个示例中,我们定义了一个hello宏,并调用了他3次,返回了3个带有固定字符串“你好我好大家好,我是 ”和自定义name的3个h1标签。实现了简单的避免代码重用的方法。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号