Jinja2 模板引擎(下):复用与扩展的核心利器
📂 所属阶段:第一阶段 — 破冰启航(基础篇)
🔗 相关章节:Jinja2 模板引擎(上) · 静态文件管理
上一篇我们啃下了Jinja2的变量注入、循环控制、分支判断三板斧,能写单页面渲染了。但要做有登录/页脚/侧边栏的完整网站,复制粘贴一套导航改N次可太笨了😤
这篇就解锁复用、扩展的核心玩法:模板继承、片段包含、自定义功能(过滤器+全局函数),配合三层继承/内置变量,直接能用做生产级模板的基础。
1. 模板继承:最常用的复用方案 ✨
1.1 为什么用继承?别再复制粘贴了!
先看痛点对比,比文字更直观:
:::success ❷ 有继承的爽感
:::
1.2 先搭「父模板」:定义共享骨架
父模板(通常叫 base.html)就是整个网站的“空壳”——用 {% block 块名 %}{% endblock %} 标记出子模板能覆盖/填充的内容,剩下的都是固定死的。
块名要语义化!比如 title、extra_head、content、scripts,覆盖时一眼就懂。
1.3 再写「子模板」:填充/覆盖特定块
子模板必须第一行用 {% extends "父模板路径" %} 声明继承关系,之后只能覆盖/补充父模板的 block,不能写块外的零散内容。
如果子模板想保留父模板的块内容,再加自己的东西,可以用 {{ super() }}。比如子模板想在通用导航后面加一个「文章搜索框」,就可以覆盖 navbar 块,开头先放 {{ super() }}。
这里写一个文章列表页的子模板:
1.4 进阶:三层继承(复杂项目救星)
如果你的网站有多个模块(比如「文章模块」「用户模块」),每个模块又有自己的共享侧边栏,可以加中层子模板。
继承层级最多3层!超过的话找块覆盖会绕晕自己。
2. include:独立片段的“插入器” 📎
2.1 什么时候用include?
和继承不同,{% include %} 是把独立的、没有继承关系的模板片段原样插入。适合用在:
- 多个页面共享的小功能组件(比如搜索框、热门文章侧边栏、评论区、分享按钮)
- 不需要覆盖/补充的纯静态片段
2.2 include 的用法
先写独立片段(通常加下划线 _ 前缀,防止被直接访问):
然后在需要的地方插入:
3. 自定义过滤器:加工数据的“小工具” 🔧
Jinja2自带了一些过滤器(比如 upper、truncate),但如果需要定制数据格式(比如自定义日期显示、字数截断(单词/中文分开算)、敏感词替换),就得自己写。
3.1 注册自定义过滤器(两种方式)
以Flask为例,注册在 app.py 或单独的 utils.py 里都行:
3.2 在模板中使用
和自带过滤器一样,用 | 调用,带参数的话加括号:
4. 自定义全局函数:随时调用的“全局助手” 🛠️
全局函数和变量的区别是:函数可以传参数、动态计算(比如获取当前登录用户的未读消息数、获取热门标签),不需要在每个视图函数里手动传入模板。
4.1 注册全局函数
4.2 在模板中使用
直接调用就行,不用传任何视图里的变量:
5. 小结与最佳实践
核心知识点回顾
避坑与最佳实践
- 继承层级≤3层:多了难维护
- 块名语义化:
content、extra_head比block1、block2好 - 独立片段加下划线:防止被路由直接访问(Flask默认不访问下划线开头的文件,但养成习惯)
- 全局变量/函数不要滥用:视图能传的小数据就不要做成全局的
- 日期/数字处理优先用过滤器:不要在模板里写复杂的Python代码
🔗 扩展阅读

