WEB开发 - Flask 入门:Jinja2 模板语法进阶 Python

在上一阶段,我们一起学习了基于Python地 web框架Flask,并且初步了解了这个框架有一种渲染方式叫做 模板语法,今天,我们一起再来深入地了解和学习这个叫做Jinja2地模板语法。

WEB开发 - Flask 入门:由浅入深地带你学习

Flask 的模板渲染由Jinja2提供支持,Jinja2 是一个强大的 Python 模板引擎。现在假设你已经对它有了基本的了解,所以接下来让我们更深入地了解 Flask 模板渲染的高级功能和最佳实践。

1. Jinja2 模板语法回顾

在进一步介绍之前,这里先简单概述一下 Jinja2 的语法:

  • 变量{``{ variable }}
  • 控制结构{% if condition %} ... {% endif %}{% for item in items %} ... {% endfor %}
  • 筛选器{``{ variable|filter_name }}
  • 评论{# This is a comment #}
  • 继承{% extends "base.html" %}{% block content %} ... {% endblock %}

根据上面的模板语法,我们使用一个例程来实现Jinja2 模板语法回顾:

代码示例:

1.1 变量

在模板中,我们可以通过 {``{ variable }} 来渲染变量的值。

示例:
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Jinja2 模板语法回顾</title>
</head>
<body>
    <h1>欢迎,{{ name }}!</h1>
    <p>你当前的年龄是:{{ age }}岁。</p>
</body>
</html>

1.2 控制结构

使用 {% %} 来执行控制结构,例如条件判断和循环。

条件判断:
{% if age >= 18 %}
    <p>你是成年人。</p>
{% else %}
    <p>你是未成年人。</p>
{% endif %}
循环:
<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

1.3. 过滤器

过滤器用于修改输出的值,比如格式化日期、文本转换等。使用 | 来调用过滤器。

示例:
<p>{{ "2024-12-27"|date("yyyy年MM月dd日") }}</p>
<p>{{ "Hello World"|lower }}</p>

1.4. 模板继承

可以通过 {% extends %}{% block %} 实现模板的继承和重用。

基本模板(base.html):
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}我的网站{% endblock %}</title>
</head>
<body>
    <header>
        <h1>{% block header %}欢迎来到我的网站{% endblock %}</h1>
    </header>

    <div class="content">
        {% block content %}内容区域{% endblock %}
    </div>

    <footer>
        {% block footer %}版权信息{% endblock %}
    </footer>
</body>
</html>

上面的基本模版在浏览器中的显示:

子模板(home.html):
{% extends "base.html" %}

{% block title %}首页 - 我的网站{% endblock %}

{% block content %}
    <h2>欢迎来到首页!</h2>
    <p>这里是一些重要的内容。</p>
{% endblock %}

上面的子模版在继承了基本模板之后,在浏览器中的显示(内容区域已经被子模版的内容替换掉了):

1.5. 自定义过滤器

你可以定义自定义的过滤器来对模板中的变量进行处理。

Python 代码(app.py):
from flask import Flask
from flask import render_template

app = Flask(__name__)

# 自定义过滤器函数
def reverse_string(value):
    return value[::-1]

# 注册自定义过滤器
app.jinja_env.filters['reverse'] = reverse_string

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

if __name__ == '__main__':
    app.run(debug=True)
模板代码(home.html):
<p>{{ "hello"|reverse }}</p>  <!-- 输出:olleh -->

上面的webServer 运行后,在浏览器总访问效果如下:

你会发现,输入内容"hello" 被我们自己定义的反相器reverse给倒序了。这个反相器就是一个过滤器,你可以定义很多不同的过滤器,比如字符串截取、大小写变换、日期格式转换、字符串替换等等。

1.6. 模板宏

宏类似于模板中的函数,可以用来复用代码块。

示例:(macros.html)
{% macro render_item(item) %}
    <div class="item">
        <h3>{{ item.name }}</h3>
        <p>{{ item.description }}</p>
    </div>
{% endmacro %}
使用宏:(home.html)
{% from "macros.html" import render_item %}

<div class="items">
    {% for item in items %}
        {{ render_item(item) }}
    {% endfor %}
</div>

app.js 如下

python 复制代码
from flask import Flask, render_template

# 创建一个 Flask 实例
app = Flask(__name__)

@app.route('/home')
def greet():
    # 定义要传递给模板的数据
    items = [
        {"name": "Alice", "description": "description Alice"},
        {"name": "Tom", "description": "description Tom"}
    ]
    # 将数据传递给模板
    return render_template('home.html', items=items)

# 运行应用
if __name__ == '__main__':
    app.run(debug=True)

上述代码执行后,从浏览器访问:

你会发现,模板宏被调用了,显示了名字和介绍。这个模板宏,可以被很多具有相同数据结构的页面调用。它形成了一个类似vue的 component 组件。

1.7. 模板包含

{% include %} 用于包含其他模板的内容,通常用于包含页面的共同部分。

示例:
<div class="sidebar">
    {% include "sidebar.html" %}
</div>

通过这些语法,Jinja2 提供了灵活而强大的模板引擎,能帮助我们高效地渲染动态内容,并且让页面结构更清晰、可维护。

2.模板继承(高级)

模板继承是 Jinja2 最强大的功能之一。它允许您定义一个基本模板并在子模板中扩展它,从而实现通用布局和结构的重用。

基本模板示例:
python 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}My Website{% endblock %}</title>
</head>
<body>
    <header>
        <h1>{% block header %}Welcome to My Website{% endblock %}</h1>
    </header>

    <div class="content">
        {% block content %}Content goes here{% endblock %}
    </div>

    <footer>
        {% block footer %}Footer content{% endblock %}
    </footer>
</body>
</html>
子模板示例:
python 复制代码
{% extends "base.html" %}

{% block title %}Home - My Website{% endblock %}

{% block content %}
    <h2>Welcome to the home page!</h2>
    <p>Here is some important content.</p>
{% endblock %}

这个案例和我们之前回顾的模板调用实际上一样的,在此不做赘述了,需要加深理解的可以重做一遍。

3.动态模板渲染

您可以将数据动态传递给模板。将数据操作逻辑与 Flask 视图中的渲染逻辑分开是一种很好的做法。

Flask 路线示例:
python 复制代码
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    data = {
        'name': 'John Doe',
        'age': 30,
        'items': ['apple', 'banana', 'cherry']
    }
    return render_template('home.html', data=data)
模板示例(home.html):
python 复制代码
<h1>Hello, {{ data.name }}</h1>
<p>You are {{ data.age }} years old.</p>
<ul>
    {% for item in data.items %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

4.模板上下文处理器

上下文处理器是在渲染模板之前运行的函数,允许您自动将公共变量传递给所有模板。

例子:
python 复制代码
@app.context_processor
def inject_user():
    return {'user': 'John Doe'}

这将注入user到每个模板中,因此您可以{``{ user }}在任何模板中使用它而无需明确传递它。这个有点类似Node.js 的中间件,在app.j中定义好之后,继续往下路由,可以全局使用。

5.使用自定义错误页面处理错误

Flask 提供了一种定义自定义错误页面的方法(例如 404 或 500 错误)。你可以为这些错误渲染自定义模板。

例子:
  • 包括 :用于{% include 'filename.html' %}重用模板片段。
  • 动态渲染render_template_string:有时,您可能需要从字符串而不是文件渲染模板。
  • 异步渲染:对于需要异步处理的繁重操作,您可以使用 Flask 对后台作业或流式传输数据到客户端的支持。

6.高级模板技术

  • 包括 :用于{% include 'filename.html' %}重用模板片段。
  • 动态渲染render_template_string:有时,您可能需要从字符串而不是文件渲染模板。
  • 异步渲染:对于需要异步处理的繁重操作,您可以使用 Flask 对后台作业或流式传输数据到客户端的支持。

7.测试模板

Flask 有一个内置测试客户端,你可以用它来测试你的路由和模板。使用flask.testing.TestCase,你可以断言模板的渲染是否正确。

python 复制代码
from flask import Flask, render_template
import unittest

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('home.html', name="Test")

class TemplateTest(unittest.TestCase):
    def setUp(self):
        app.config['TESTING'] = True
        self.client = app.test_client()

    def test_home_page(self):
        response = self.client.get('/')
        self.assertIn(b'Hello, Test', response.data)

if __name__ == '__main__':
    unittest.main()

8.Flask扩展

Flask 有许多可以简化模板的扩展,例如:

  • Flask-WTF:用于将表单集成到模板中。
  • Flask-Login:用于管理模板中的用户会话。

除了上面这些,其他还有 循环、嵌套等方法,都很容易实现,这里就不一一赘述了。

通过学习这些高级特性,你可以更灵活地使用 Flask 的模板系统,编写更加干净、可维护和扩展的模板。你可以尝试将这些功能组合在一起,用于实现更复杂的页面和功能。如果有任何问题或不清楚的地方,欢迎随时留言一起来讨论!

相关推荐
MinIO官方账号25 分钟前
使用亚马逊针对 PyTorch 和 MinIO 的 S3 连接器实现可迭代式数据集
人工智能·pytorch·python
四口鲸鱼爱吃盐28 分钟前
Pytorch | 利用IE-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
人工智能·pytorch·python·深度学习·计算机视觉
四口鲸鱼爱吃盐30 分钟前
Pytorch | 利用EMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
人工智能·pytorch·python
lvbu_2024war011 小时前
MATLAB语言的网络编程
开发语言·后端·golang
问道飞鱼1 小时前
【Springboot知识】Springboot进阶-实现CAS完整流程
java·spring boot·后端·cas
游客5201 小时前
自动化办公-合并多个excel
开发语言·python·自动化·excel
Q_19284999061 小时前
基于Spring Boot的电影网站系统
java·spring boot·后端
豌豆花下猫1 小时前
Python 潮流周刊#83:uv 的使用技巧(摘要)
后端·python·ai
凡人的AI工具箱2 小时前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
RacheV+TNY2642782 小时前
深度解析:电商平台API接口的安全挑战与应对策略
人工智能·python·自动化·api