jinja2 模板与 Django 模板对比总结

Jinja2 是一个基于 Python 的模板引擎,广泛用于生成 HTML、XML 或其他标记语言。它被许多框架(如 Flask 和 Django)使用,具有灵活的语法和强大的功能。对比 Django 的模板,总结一下 Jinja2。

0. 官网

  • 官方文档Jinja2 官方文档
  • Flask 教程:Flask 框架中大量使用 Jinja2,学习 Flask 时可以顺便掌握 Jinja2。
  • 在线练习:使用在线 Python 环境(如 Replit)练习 Jinja2 模板渲染。

1. 安装

1
pip install Jinja2

2. 设计理念

  • Jinja2
    • 更接近 Python 语法,支持更复杂的表达式和逻辑。
    • 强调灵活性和扩展性,允许在模板中执行更多的逻辑操作。
    • 适合需要高度定制化的场景。
  • Django 模板
    • 强调 “模板与逻辑分离”,鼓励将复杂的逻辑放在视图(View)中,而不是模板中。
    • 语法更简单,限制更多,适合遵循 Django 设计哲学的项目。

2. 性能

  • Jinja2
    • 性能较高,尤其是在处理复杂逻辑和大规模数据时。
    • 支持模板预编译和缓存,适合高性能场景。
  • Django 模板
    • 性能稍逊于 Jinja2,但在大多数场景下足够使用。
    • 由于设计上更简单,适合中小型项目。

3. 扩展性

  • Jinja2
    • 支持自定义过滤器、全局函数和测试器。
    • 可以通过 Python 代码直接扩展功能。
  • Django 模板
    • 支持自定义模板标签和过滤器,但扩展方式相对复杂。
    • 需要遵循 Django 的扩展机制。

4. 使用场景

  • Jinja2
    • 适合需要高度灵活性和复杂逻辑的项目。
    • 常用于 Flask、FastAPI 等框架。
    • 适合开发者更喜欢 Python 风格的语法。
  • Django 模板
    • 适合遵循 Django 设计哲学的项目。
    • 常用于 Django 框架,与 Django 的其他组件(如 ORM、表单)紧密集成。
    • 适合开发者更喜欢简单、限制较多的模板语法。

5. 语法差异

(1)变量输出

  • Jinja2:{{ variable }}
  • Django:{{ variable }}
  • 两者在变量输出语法上完全相同。

(2)控制结构

1️⃣条件判断 if 语句

Jinja2
  • 支持更复杂的表达式,可以直接在条件中组合逻辑操作。
  • 允许使用 Python 风格的条件表达式(如 inis、数学运算等)。
1
2
3
4
5
6
7
{% if user.is_admin and request.method == 'POST' %}
<p>Admin action submitted!</p>
{% elif user.age >= 18 %}
<p>Welcome, adult user!</p>
{% else %}
<p>Access denied.</p>
{% endif %}
Django 模板
  • 语法更简单,但限制较多。
  • 不支持复杂的表达式(如直接使用 >=== 等运算符),需依赖模板标签或过滤器。
示例
1
2
3
4
5
6
7
{% if user.is_admin and request.method == "POST" %}
<p>Admin action submitted!</p>
{% elif user.age > 17 %} {# Django 中不能写 `>= 18`,需用 `> 17` #}
<p>Welcome, adult user!</p>
{% else %}
<p>Access denied.</p>
{% endif %}

2️⃣循环 for 语句

Jinja2
  • 支持在 for 循环中直接添加条件(类似 Python 的列表推导式)。
  • 提供 loop 变量,包含丰富的循环元数据(如 loop.indexloop.first 等)。
示例
1
2
3
4
5
{# 直接过滤循环项 #}
{% for user in users if user.is_active %}
{{ loop.index }}. {{ user.name }}
{% if loop.first %} (First user!) {% endif %}
{% endfor %}
Django 模板
  • 不支持在 for 循环中直接添加条件,需在循环内部使用 if 标签过滤。
  • 提供 forloop 变量,功能类似但属性名不同(如 forloop.counter)。
示例
1
2
3
4
5
6
7
{% for user in users %}
{% if user.is_active %} {# 条件需写在循环内部 #}
{{ forloop.counter }}. {{ user.name }}
{% if forloop.first %} (First user!) {% endif %}
{% endif %}
{% endfor %}

3️⃣循环变量的差异

Jinja2 的 loop 变量
  • loop.index:当前迭代的索引(从 1 开始)。
  • loop.index0:当前迭代的索引(从 0 开始)。
  • loop.first:是否是第一次迭代。
  • loop.last:是否是最后一次迭代。
  • loop.length:总迭代次数。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
{% for item in items %}
{{ loop.index }} of {{ loop.length }}: {{ item }}
{% endfor %}
<hr>

{% for n in list3 %}
<p>列表第{{ loop.index }}位是{{ n }},列表总长度为{{ loop.length }}</p>
{% endfor %}

<hr>
{% for n in list3 %}
<p>列表第{{ loop.index0 }}位是{{ n }},列表总长度为{{ loop.length }}</p>
{% endfor %}
Django 模板的 forloop 变量
  • forloop.counter:当前迭代的索引(从 1 开始)。
  • forloop.counter0:当前迭代的索引(从 0 开始)。
  • forloop.revcounter:反向索引(从总长度到 1)。
  • forloop.first/forloop.last:同 Jinja2。

示例

1
2
3
{% for item in items %}
{{ forloop.counter }} of {{ forloop.revcounter }}: {{ item }}
{% endfor %}

4️⃣对复杂表达式的支持

Jinja2
  • 允许在控制结构中直接使用 Python 风格的表达式
  • 支持数学运算、逻辑操作、函数调用等。

示例

1
2
3
{% if (user.score * 1.2) > 100 and user.name.startswith('A') %}
<p>Special user!</p>
{% endif %}
Django 模板
  • 不支持复杂的表达式,需通过自定义模板标签或过滤器实现。
  • 简单逻辑可以通过 with 标签或过滤器组合实现。

示例

1
2
3
4
5
{% with multiplied_score=user.score|multiply:1.2 %}
{% if multiplied_score > 100 and user.name|startswith:'A' %}
<p>Special user!</p>
{% endif %}
{% endwith %}

5️⃣ else 分支的差异

Jinja2

  • for 循环支持 else 分支,当循环未执行时触发。

示例

1
2
3
4
5
{% for user in users %}
{{ user.name }}
{% else %}
<p>No users found.</p>
{% endfor %}

Django 模板

  • 不支持 for...else,需通过检查列表是否为空来实现类似功能。

示例

1
2
3
4
5
6
7
{% if users %}
{% for user in users %}
{{ user.name }}
{% endfor %}
{% else %}
<p>No users found.</p>
{% endif %}

(3)过滤器

  • Jinja2:{{ variable|filter }}
  • Django:{{ variable|filter }}
  • Jinja2 提供了更多的内置过滤器,例如 mapselectreject 等。
  • Django 的过滤器更简单,但可以通过自定义模板标签和过滤器扩展。
  • 两者都支持过滤器,但内置过滤器的名称和功能可能有所不同。

(4)注释

  • Jinja2:``
  • Django:``
  • 注释语法完全相同。

(5)模板继承

  • 两者都支持模板继承,语法几乎相同:
    • Jinja2:{% extends "base.html" %}
    • Django:{% extends "base.html" %}

(6)全局函数和变量

  • Jinja2 支持在模板中定义全局函数和变量。
  • Django 模板更依赖上下文处理器(Context Processors)来传递全局变量。

6. 总结对比表

功能 Jinja2 Django 模板
条件中的复杂表达式 支持(如 >=, in, is 不支持,需用简单逻辑或过滤器
for 循环中的条件 允许直接在 for 后添加条件 需在循环内部使用 if 标签
循环变量 loop.index, loop.first forloop.counter, forloop.first
for...else 支持 不支持,需用 if 检查列表是否为空
数学运算和函数调用 允许直接使用(如 user.score * 1.2 需自定义过滤器或 with 标签

7. 选择建议

  • Jinja2:适合需要灵活性和复杂逻辑的场景(如 Flask、FastAPI 项目)。
  • Django 模板:适合遵循 Django 设计哲学,强调模板与业务逻辑分离的项目。

两者的差异主要体现在语法灵活性和功能扩展性上,根据项目需求选择即可!

8. 部分测试例子

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<h1>Hello</h1>

<p>测试 jinja2</p>
{% for i in range(10) if i % 2 == 0 %}
{{ i }}
{% endfor %}
<hr>

<p>支持更复杂的表达式,可以直接在条件中组合逻辑操作。</p>
{% if users.1.age >= 19 %}
<p>{{ users.1.name }}的年龄大于等于19</p>
{% endif %}
<hr>
<p>允许使用 Python 风格的条件表达式(如 in、is、数学运算等)。</p>
{% if 1 in list1 %}
<p>1 in list1</p>
{% elif 1 not in list1 %}
<p>1 not in list1</p>
{% endif %}
<hr>
<p>支持在 `for` 循环中直接添加条件(类似 Python 的列表推导式)。</p>

{% for user in users if user.age >=18 %}
<p>{{ user.name }}的年龄为{{ user.age }}已成年。</p>
{% endfor %}
<hr>
<p>提供 `loop` 变量,包含丰富的循环元数据(如 `loop.index`、`loop.first` 等)。</p>
{% for n in list3 %}
<p>列表第{{ loop.index }}位是{{ n }},列表总长度为{{ loop.length }}</p>
{% endfor %}

<hr>
{% for n in list3 %}
<p>列表第{{ loop.index0 }}位是{{ n }},列表总长度为{{ loop.length }}</p>
{% endfor %}
<hr>
<p>允许在控制结构中直接使用 Python 风格的表达式。</p>
<p>支持数学运算、逻辑操作、函数调用等。</p>
{% if (users.3.score * 1.2) > 100 and users.3.name.startswith('王') %}
<p>{{ users.3.name }}---Special user!</p>
{% endif %}
<hr>
<p>for 循环支持 else 分支,当循环未执行时触发。</p>
{% for user in users1 %}
{{ user.name }}
{% else %}
<p>No users found.</p>
{% endfor %}


</body>
</html>

9. 补充

Django 模板和 Jinja2 模板在生成 URL 时的主要区别在于它们的语法和使用方式。虽然两者的功能相似,但它们的实现方式和一些细节有所不同。以下是两者的详细对比:

9.1 Django 模板中的 url 标签

语法

在 Django 模板中,{% url %} 是一个模板标签,用于动态生成 URL。它的语法如下:

1
{% url 'view_name' arg1 arg2 ... %}

或者使用关键字参数:

1
{% url 'view_name' arg1=value1 arg2=value2 ... %}

特点

  1. 直接使用模板标签{% url %} 是 Django 模板语言的一部分,不需要额外导入或配置。
  2. 参数传递方式灵活:支持位置参数和关键字参数。
  3. 与 Django 的 URL 配置紧密集成{% url %} 直接解析 Django 的 urls.py 配置。

示例

假设你的 URL 配置如下:

1
2
3
4
5
6
7
# urls.py
from django.urls import path
from . import views

urlpatterns = [
path('manualPagination/<int:page>/', views.manual_pagination, name='manualPagination'),
]

在 Django 模板中,你可以这样生成 URL:

1
<a href="{% url 'manualPagination' page=1 %}">第一页</a>

9.2 Jinja2 模板中的 url 函数

语法

在 Jinja2 模板中,url 是一个函数,用于动态生成 URL。它的语法如下:

jinja2 复制

1
{{ url('view_name', kwargs={'arg1': value1, 'arg2': value2}) }}

特点

  1. 需要显式传递参数:Jinja2 的 url 函数需要通过 kwargs 参数传递路径参数,不能直接使用关键字参数。
  2. 需要在环境中注册:在使用 Jinja2 时,必须在 Jinja2 环境中注册 url 函数(通常是 Django 的 reverse 函数)。
  3. 语法更接近 Python:Jinja2 是一个独立的模板引擎,其语法更接近 Python,适合需要更灵活处理逻辑的场景。

示例

假设你的 URL 配置与上面相同:

Python 复制

1
2
3
4
5
6
7
# urls.py
from django.urls import path
from . import views

urlpatterns = [
path('manualPagination/<int:page>/', views.manual_pagination, name='manualPagination'),
]

在 Jinja2 模板中,你可以这样生成 URL:

jinja2 复制

1
<a href="{{ url('manualPagination', kwargs={'page': 1}) }}">第1页</a>

9.3 Django 模板与 Jinja2 模板生成 URL 的主要区别

特点 Django 模板 {% url %} Jinja2 模板 url 函数
语法 使用模板标签 {% url %} 使用函数 url(),需要通过 kwargs 传递参数
参数传递 支持位置参数和关键字参数 只能通过 kwargs 传递参数
环境配置 不需要额外配置 需要在 Jinja2 环境中注册 url 函数
灵活性 简单易用,适合 Django 原生模板 更灵活,适合需要复杂逻辑的场景
性能 性能优化,适合 Django 项目 性能稍逊于 Django 模板,但差距不大
与 Django 的集成 与 Django 的 URL 配置紧密集成 需要手动将 reverse 函数注册到 Jinja2 环境中

9.4 推荐使用场景

  • **Django 模板 {% url %}**:
    • 适合纯 Django 项目,不需要额外配置。
    • 适合简单的模板逻辑,语法简洁易懂。
    • 对于熟悉 Django 的开发者来说,使用起来非常自然。
  • Jinja2 模板 url 函数
    • 适合需要更灵活模板逻辑的项目。
    • 如果项目中已经使用了 Jinja2,可以统一模板语法。
    • 适合需要与 Python 代码更紧密集成的场景。

9.5 总结

Django 模板和 Jinja2 模板在生成 URL 时的主要区别在于语法和使用方式。Django 模板的 {% url %} 标签更简单易用,适合 Django 原生项目;而 Jinja2 的 url 函数更灵活,适合需要复杂逻辑的场景。根据你的项目需求和开发习惯,选择合适的模板引擎即可。

10. 相关参考