在Web开发中,我们常常需要将后端的数据(如用户信息、商品列表、文章内容等)展示到前端页面上。如果手动拼接HTML和数据,会变得非常繁琐且容易出错。而模板引擎(Template Engine)正是解决这个问题的工具——它允许我们在HTML中嵌入动态内容,让后端数据“注入”到页面中,生成最终的网页。
一、什么是Jinja2和模板引擎?¶
模板引擎的核心作用是将后端数据与HTML模板结合,生成可直接展示给用户的网页。它就像一个“模板工具”,让开发者专注于数据逻辑和页面结构的分离,而不是重复编写静态HTML和动态数据拼接的代码。
Jinja2 是Flask框架的默认模板引擎,由Python实现,语法简洁且功能强大。它支持变量替换、条件判断、循环、过滤器等功能,能高效地处理动态数据渲染。
二、在Flask中使用Jinja2的基本流程¶
要在Flask中使用Jinja2,只需遵循以下步骤:
1. 准备环境:安装Flask¶
首先确保已安装Flask。如果未安装,可通过pip安装:
pip install flask
2. 创建Flask应用与路由¶
在项目根目录下创建app.py,定义一个简单的Flask应用和路由,用于提供数据和渲染模板:
from flask import Flask, render_template # 导入Flask和模板渲染工具
app = Flask(__name__) # 创建Flask应用实例
# 定义路由,访问首页时执行index函数
@app.route('/')
def index():
# 准备后端数据(可以是字典、列表、对象等)
user_info = {
'name': '小明',
'age': 20,
'hobbies': ['篮球', '编程', '阅读'], # 爱好列表
'is_student': True, # 是否是学生
'posts': [ # 文章列表
{'title': 'Python入门教程', 'author': '小明', 'date': '2023-01-15'},
{'title': 'Flask实战', 'author': '小明', 'date': '2023-02-20'}
]
}
# 渲染模板并返回数据
return render_template('index.html', **user_info) # **user_info将字典拆分为参数
if __name__ == '__main__':
app.run(debug=True) # 调试模式运行
3. 创建模板文件¶
Flask默认会在项目根目录下的templates文件夹中寻找模板文件(若不存在需手动创建)。因此,需在项目根目录新建templates文件夹,并在其中创建index.html作为模板文件:
项目结构:
your_project/
├── app.py # Flask应用代码
└── templates/ # 模板文件夹
└── index.html # 模板文件
4. 在模板中使用Jinja2语法¶
在templates/index.html中,使用Jinja2语法嵌入动态数据:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ name }}的个人主页</title>
</head>
<body>
<h1>欢迎访问{{ name }}的主页!</h1>
<!-- 变量替换:直接显示后端传递的name -->
<p>年龄:{{ age }}岁</p>
<!-- 条件判断:根据年龄判断是否成年 -->
{% if age >= 18 %}
<p>状态:成年人</p>
{% else %}
<p>状态:未成年人</p>
{% endif %}
<!-- 循环遍历:展示爱好列表 -->
<h2>我的爱好</h2>
<ul>
{% for hobby in hobbies %}
<li>{{ loop.index }}. {{ hobby }}</li> <!-- loop.index显示序号 -->
{% endfor %}
</ul>
<!-- 条件+循环:展示文章列表 -->
<h2>我的文章</h2>
<table border="1">
<tr>
<th>标题</th>
<th>作者</th>
<th>发布日期</th>
</tr>
{% for post in posts %}
<tr>
<td>{{ post.title }}</td>
<td>{{ post.author }}</td>
<td>{{ post.date }}</td>
</tr>
{% endfor %}
</table>
<!-- 嵌套对象数据:判断是否为学生 -->
{% if is_student %}
<p>身份:在校学生</p>
{% else %}
<p>身份:社会人士</p>
{% endif %}
</body>
</html>
5. 运行应用并测试¶
启动app.py:
python app.py
访问http://127.0.0.1:5000,即可看到动态渲染的页面,包含小明的信息、爱好列表和文章列表。
三、Jinja2核心语法速览¶
上面的示例中已经用到了Jinja2的基本语法,以下是最常用的核心功能:
1. 变量替换¶
用{{ 变量名 }}在模板中嵌入后端传递的变量。例如:
<p>用户名:{{ user.name }}</p> <!-- 后端传递user字典 -->
<p>价格:{{ product.price }}</p> <!-- 后端传递product对象 -->
2. 条件判断(if-else)¶
用{% if ... %}、{% else %}、{% elif %}实现条件逻辑。例如:
{% if is_logged_in %}
<p>欢迎回来!</p>
{% else %}
<p>请先登录</p>
{% endif %}
3. 循环遍历(for)¶
用{% for ... %}遍历列表、字典或其他可迭代对象。常用变量:
- loop.index:当前循环的序号(从1开始)
- loop.first:是否为循环的第一个元素(布尔值)
- loop.last:是否为循环的最后一个元素(布尔值)
例如遍历爱好列表:
{% for hobby in hobbies %}
<li>{{ hobby }}</li>
{% endfor %}
4. 过滤器(Filter)¶
Jinja2支持过滤器对变量进行处理(如格式化、转换等),用|连接过滤器名。例如:
- {{ name|upper }}:将字符串转为大写
- {{ date|format('%Y-%m-%d') }}:格式化日期(需结合Python的datetime)
- {{ text|truncate(20) }}:截断长文本为20个字符
示例:
<p>标题:{{ post.title|truncate(15) }}</p> <!-- 截断标题长度 -->
四、进阶技巧:模板继承¶
当项目中有多个页面(如首页、文章页、个人中心)时,重复编写相同的HTML结构(如导航栏、页脚)会很麻烦。Jinja2支持模板继承,通过base.html作为基础模板,其他页面“继承”并扩展它。
1. 创建基础模板(base.html)¶
在templates文件夹中创建base.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<nav>
<a href="/">首页</a> | <a href="/about">关于</a>
</nav>
<main>
{% block content %}{% endblock %} <!-- 内容区块,子模板可覆盖 -->
</main>
<footer>© 2023 我的网站</footer>
</body>
</html>
2. 子模板继承(index.html)¶
在index.html中通过{% extends "base.html" %}继承基础模板,并覆盖block:
{% extends "base.html" %} <!-- 继承base.html -->
{% block title %}小明的主页{% endblock %} <!-- 覆盖标题区块 -->
{% block content %} <!-- 覆盖内容区块 -->
<h1>欢迎来到小明的主页!</h1>
<p>这是继承base.html后的内容。</p>
{% endblock %}
五、总结¶
Jinja2模板引擎让Flask后端数据的前端渲染变得简单直观。通过变量替换、条件判断、循环等语法,我们可以轻松实现动态页面;而模板继承则进一步提高了代码复用性,让项目结构更清晰。
掌握Jinja2后,你可以继续探索更多高级功能,如宏(Macro,复用代码片段)、测试过滤器、自定义函数等。随着实践的深入,你会发现模板引擎是Web开发中连接数据与用户界面的核心工具。
提示:初学者建议先从简单示例(如本文的个人主页)入手,逐步尝试复杂场景(如数据库查询结果渲染、表单数据动态回显),再深入学习模板继承和高级语法。