jinja2模板引擎全面解析
jinja2模板介绍
jinja2的开发是参考了django的模板,跟django模板有很多类似的地方,但它扩展了一种表达性语言,提供了一套更强大的工具。
jinja2特性:
沙箱中执行
强大的HTML自动转义系统保护系统免受XSS
模板继承
及时编译最优的python代码
可选提前编译模板的时间
易于调试、异常的行数直接指向模板中的对应行
可配置的语法
安装Flask时会自带安装jinja2,也可单独安装:
pip install jinja2
模板渲染
视图调用模板:
在项目目录下创建
templates
目录存放模板文件在视图函数中使用
render_template
调用模板文件
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():return render_template('index.html') # 渲染模板
传递变量到模板:
@app.route('/')
def index():# 直接传递变量return render_template('index.html', name='Jack', age=18)# 或通过字典解包传递context = {'name': 'Tom', 'age': 18}return render_template('index.html', **context)
模板中使用变量:
<h3>name: {{ name }}</h3> <!-- 输出:Jack -->
<h3>age: {{ age }}</h3> <!-- 输出:18 -->
<h3>height: {{ height }}</h3> <!-- 不存在的变量显示为空 -->
基本语法
1. 变量定义
全局变量:
{% set height = 10086 %}
{{ height }} <!-- 输出:10086 -->
局部变量(使用with
语句):
{% with say = 'very good' %}{{ say }} <!-- 输出:very good -->
{% endwith %}
2. 控制语句
条件语句:
{% if color == 'red' %}<div style="color:red">我很红</div> <!-- color='red'时显示 -->
{% else %}<div style="color:lime">我不红了</div> <!-- 其他情况显示 -->
{% endif %}
循环语句:
<!-- 遍历列表 -->
{% set list = ['青铜','白银','黄金','钻石'] %}
{% for item in list %}{{ loop.index }}.{{ item }} <!-- 输出:1.青铜 2.白银 3.黄金 4.钻石 -->
{% endfor %}
<!-- 遍历字典 -->
{% set my_dict = {'name': 'Jack', 'age': 28} %}
{% for key, value in my_dict.items() %}<h3>{{ key }}: {{ value }}</h3> <!-- 输出:name: Jack age: 28 -->
{% endfor %}
<!-- 空列表处理 -->
{% for user in [] %}<li>{{ user.username }}</li>
{% else %}<li><em>没有找到用户</em></li> <!-- 输出:没有找到用户 -->
{% endfor %}
循环内置变量:
变量 | 描述 | 示例 |
---|---|---|
loop.index | 当前迭代索引(从1开始) | {{ loop.index }} → 1 |
loop.index0 | 当前迭代索引(从0开始) | {{ loop.index0 }} → 0 |
loop.first | 是否是第一次迭代 | {{ loop.first }} → True |
loop.last | 是否是最后一次迭代 | {{ loop.last }} → False |
loop.length | 序列长度 | {{ loop.length }} → 4 |
3. 运算符
{{ 5 + 3 }} <!-- 输出:8 -->
{{ "Hello" ~ " " ~ "World" }} <!-- 输出:Hello World -->
{{ 10 / 2 }} <!-- 输出:5.0 -->
{{ 10 % 3 }} <!-- 输出:1 -->
{{ 2 ** 3 }} <!-- 输出:8 -->
{{ "a" in "abc" }}<!-- 输出:True -->
{{ "Hello" * 3 }} <!-- 输出:HelloHelloHello -->
过滤器
常用内置过滤器
字符串操作:
过滤器 | 作用 | 示例 | 输出结果 |
---|---|---|---|
safe | HTML转义 | {{ '<b>Hi</b>' | safe }} | Hi(粗体显示) |
capitalize | 首字母大写其余小写 | {{ 'hello WORLD' | capitalize }} | "Hello world" |
lower | 转小写 | {{ 'HELLO' | lower }} | "hello" |
upper | 转大写 | {{ 'hello' | upper }} | "HELLO" |
title | 单词首字母大写 | {{ 'hello world' | title }} | "Hello World" |
trim | 删除首尾空格 | {{ ' hello ' | trim }} | "hello" |
reverse | 字符串反转 | {{ 'abc' | reverse }} | "cba" |
truncate | 截断字符串 | {{ 'long text here' | truncate(9) }} | "long text..." |
replace | 替换字符串 | {{ 'hello' | replace('l', '1') }} | "he11o" |
striptags | 移除HTML标签 | {{ '<b>text</b>' | striptags }} | "text" |
列表操作:
过滤器 | 作用 | 示例 | 输出结果 |
---|---|---|---|
first | 获取第一个元素 | {{ [1,2,3] | first }} | 1 |
last | 获取最后一个元素 | {{ [1,2,3] | last }} | 3 |
length | 获取列表长度 | {{ [1,2,3] | length }} | 3 |
sum | 列表求和 | {{ [1,2,3] | sum }} | 6 |
sort | 列表排序 | {{ [3,1,2] | sort }} | [1,2,3] |
join | 拼接列表元素 | {{ ['a','b','c'] | join('-') }} | "a-b-c" |
数值操作:
过滤器 | 作用 | 示例 | 输出结果 |
---|---|---|---|
round | 四舍五入 | {{ 3.1415 | round(2) }} | 3.14 |
abs | 绝对值 | {{ -5 | abs }} | 5 |
int | 转换为整数 | {{ 3.9 | int }} | 3 |
float | 转换为浮点数 | {{ '3.14' | float }} | 3.14 |
日期时间操作:
过滤器 | 作用 | 示例 | 输出结果 |
---|---|---|---|
datetime | 格式化日期时间 | {{ now | datetime('%Y-%m-%d') }} | "2023-10-15" |
date | 格式化日期 | {{ now | date('%m/%d/%Y') }} | "10/15/2023" |
time | 格式化时间 | {{ now | time('%H:%M') }} | "14:30" |
自定义过滤器
方式一:使用add_template_filter
# 自定义过滤器:将数字转为中文大写
def to_chinese(num):chinese_nums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']return ''.join(chinese_nums[int(d)] for d in str(num))
app.add_template_filter(to_chinese, 'chinese') # 注册为过滤器
模板中使用:
{{ 12345 | chinese }} <!-- 输出:壹贰叁肆伍 -->
方式二:使用装饰器
# 自定义过滤器:过滤列表中的偶数
@app.template_filter('even_only')
def filter_even(nums):return [n for n in nums if n % 2 == 0]
模板中使用:
{{ [1,2,3,4,5,6] | even_only }} <!-- 输出:[2,4,6] -->
带参数的过滤器:
# 自定义过滤器:按指定倍数缩放数值
@app.template_filter('scale')
def scale_filter(value, factor=1):return value * factor
模板中使用:
{{ 10 | scale(2.5) }} <!-- 输出:25.0 -->
{{ 5 | scale }} <!-- 输出:5(使用默认倍数1) -->
复杂示例:
# 自定义过滤器:生成星级评分
@app.template_filter('stars')
def star_rating(rating, max_stars=5):full_stars = '★' * int(rating)half_star = '½' if (rating - int(rating)) >= 0.5 else ''empty_stars = '☆' * (max_stars - len(full_stars + half_star))return full_stars + half_star + empty_stars
模板中使用:
{{ 4.5 | stars }} <!-- 输出:★★★★½ -->
{{ 3 | stars(10) }} <!-- 输出:★★★☆☆☆☆☆☆☆ -->