python+flask后端开发系列 | Jinja2下HTML模板的继承机制与应用场景

简介:在 Flask 开发中,Jinja2 模板引擎的继承机制是提升开发效率和代码可维护性的关键工具。 本文将带你深入了解 Jinja2 模板继承的核心功能,从基础概念到实际应用,帮助你掌握如何通过模板继承构建高效且可复用的代码结构。我们不仅会探讨如何定义父模板和子模板,还会通过实际案例展示如何在多页面布局、动态内容加载和组件化开发中灵活应用模板继承。
目录:
一、Jinja2模板的继承机制
1.1 模板继承的基本概念
1.2 如何定义父模板
1.3 如何定义子模板
二、Jinja2模板继承的功能使用案例
2.1 基础模板继承
2.2 添加动态内容
2.3 覆盖父模板内容
三、Jinja2模板集成的应用场景
3.1 多页面布局
3.2 动态内容加载
3.3 组件化开发
四、结束语
🚀 读完本文,你将解锁以下超实用技能和知识储备:
- 🔗 理解 Jinja2 模板的继承机制:掌握如何通过模板继承,构建高效且可复用的代码结构。
- 🛠️ 掌握 Jinja2 模板中的控制语句:学会在模板中灵活运用动态内容的展示。
- 🌟 学会在实际项目中应用模板继承:将理论知识转化为实际操作,提升项目开发效率。
- 💡 提升 Flask + Jinja2 开发效率和代码可维护性:通过模板继承,让你的代码更加简洁且易于维护。
一、Jinja2模板的继承机制
1.1 模板继承的基本概念
在 Flask 开发中,Jinja2 模板引擎提供了强大的模板继承功能。模板继承允许你定义一个 父模板,并在其中定义可被子模板覆盖的 块(blocks)。子模板可以继承父模板的结构,同时覆盖或扩展父模板中的特定部分。这种方式可以显著减少模板代码的重复,提高开发效率。基本语法如下:
1.2 如何定义父模板
父模板是模板继承的基础,它定义了页面的整体结构和布局。以下是一个简单的父模板示例:
<!-- base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<header>
<h1>我的网站</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于我们</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}
<p>这是默认内容。</p>
{% endblock %}
</main>
<footer>
<p>© 2025 我的网站</p>
</footer>
</body>
</html>
在父模板中,我们定义了两个块:title 和 content。这些块允许在子模板中被覆盖。
1.3 如何定义子模板
子模板通过 extends 语句继承父模板,并可以覆盖父模板中的块。以下是一个子模板的示例:
<!-- index.html -->
{% extends "base.html" %}
{% block title %}首页 - 我的网站{% endblock %}
{% block content %}
<h1>欢迎来到首页</h1>
<p>这里是首页的内容。</p>
{% endblock %}
在这个子模板中,我们覆盖了父模板中的 title 和 content 块,从而实现了页面内容的定制。注意,子模板与父模板需要在同级目录下,否则需要在继承位置中添加父模板的相对路径。同时,子模板中,每个块(blocks)都需要前后对应,以{% blockname %} 内容 {% endblock %}的格式进行框定。
二、Jinja2模板继承的功能使用案例
2.1 基础模板继承
基础模板继承是模板继承的核心功能。通过继承父模板,子模板可以复用父模板的结构,同时覆盖或扩展特定部分。以下是一个完整的示例:
- Flask后端代码:
# -*- coding: utf-8 -*-
from flask import Flask, render_template
from datetime import datetime
app = Flask(__name__)
# 定义自定义过滤器
def datetimeformat(value, format='%Y-%m-%d %H:%M:%S'):
return value.strftime(format)
# 注册过滤器
app.jinja_env.filters['datetimeformat'] = datetimeformat
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run()
- 父模板(base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<header>
<h1>头部header</h1>
<h1>我的网站,我来自父模板</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于父模板</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}
<p>这是默认内容。</p>
{% endblock %}
</main>
<footer>
<h1>尾部footer</h1>
<p>© 2025 我的网站</p>
</footer>
</body>
</html>
- 子模板(index.html):
{% extends "base.html" %}
{% block title %}首页 - 子模板的网站{% endblock %}
{% block content %}
<h1>欢迎来到子模板的首页</h1>
<p>这里是子模板的内容。</p>
{% endblock %}
- 渲染结果:

2.2 添加动态内容
在模板继承中,你可以在子模板中添加动态内容。以下是一个示例,展示如何在子模板中使用 Flask 传递的变量:
- Flask 后端代码:
# -*- coding: utf-8 -*-
from flask import Flask, render_template
from datetime import datetime
app = Flask(__name__)
# 定义自定义过滤器
def datetimeformat(value, format='%Y-%m-%d %H:%M:%S'):
return value.strftime(format)
# 注册过滤器
app.jinja_env.filters['datetimeformat'] = datetimeformat
@app.route('/')
def index():
return render_template('index.html', current_time=datetime.now())
if __name__ == '__main__':
app.run()
- 子模板(index.html):
{% extends "base.html" %}
{% block title %}首页 - 我的网站{% endblock %}
{% block content %}
<h1>欢迎来到首页</h1>
<p>当前时间:{{ current_time | datetimeformat}}</p>
{% endblock %}
- 渲染结果:

上述示例中,我采用自定义过滤器对实时获取的时间进行格式化,并将其传递到子模板index.html中进行实时显示。(关于过滤器的使用,大家可以一键访问直达我之前的文章:python+flask后端开发系列 | Jinja2模板下,过滤器的使用)
2.3 覆盖父模板内容
你可以在子模板中完全覆盖父模板的块,也可以在父模板的基础上扩展内容。以下是一个扩展内容的示例:
- 父模板(base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<header>
<h1>头部header</h1>
<h1>我的网站,我来自父模板</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于父模板</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}
<p>这是默认内容。</p>
{% endblock %}
</main>
<footer>
<h1>尾部footer</h1>
<p>© 2025 我的网站</p>
</footer>
</body>
</html>
- 子模板(index.html):
{% extends "base.html" %}
{% block title %}首页 - 我的网站{% endblock %}
{% block content %}
<h1>欢迎来到首页</h1>
<p>这里是首页的内容。</p>
{% endblock %}
- 渲染结果:

三、Jinja2模板集成的应用场景
3.1 多页面布局
模板继承非常适合多页面布局。你可以定义一个通用的父模板,然后为每个页面创建一个子模板。这样可以避免重复编写公共部分的代码,提高开发效率,便于维护。
- Flask后端代码:
# -*- coding: utf-8 -*-
from flask import Flask, render_template
from datetime import datetime
app = Flask(__name__)
# 定义自定义过滤器
def datetimeformat(value, format='%Y-%m-%d %H:%M:%S'):
return value.strftime(format)
# 注册过滤器
app.jinja_env.filters['datetimeformat'] = datetimeformat
@app.route('/')
def index():
return render_template('index.html')
@app.route('/about')
def aboutx():
return render_template('about.html')
if __name__ == '__main__':
app.run()
- 父模板(base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<header>
<h1>头部header</h1>
<h1>我的网站,我来自父模板</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于父模板</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}
<p>这是默认内容。</p>
{% endblock %}
</main>
<footer>
<h1>尾部footer</h1>
<p>© 2025 我的网站</p>
</footer>
</body>
</html>
- 子模板-1(index.html):
{% extends "base.html" %}
{% block title %}首页 - 子模板的网站{% endblock %}
{% block content %}
<h1>欢迎来到子模板的首页</h1>
<p>这里是子模板的内容。</p>
{% endblock %}
- 子模板-2(about.html):
{% extends "base.html" %}
{% block title %}关于我们 - 我的网站{% endblock %}
{% block content %}
<h1>关于我们,子模板-2的网站</h1>
<p>这里是关于我们页面的内容。</p>
{% endblock %}
- 渲染结果:

3.2 动态内容加载
模板继承可以方便地加载动态内容。通过在父模板中定义块,并在子模板中覆盖这些块,你可以实现动态内容的加载。
- Flask后端代码:
from flask import Flask, render_template
from datetime import datetime
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html', current_time=datetime.now())
if __name__ == '__main__':
app.run()
- 父模板(base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<header>
<h1>头部header</h1>
<h1>我的网站,我来自父模板</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于父模板</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}
<p>这是默认内容。</p>
{% endblock %}
</main>
<footer>
<h1>尾部footer</h1>
<p>© 2025 我的网站</p>
</footer>
</body>
</html>
- 子模板(index.html):
{% extends "base.html" %}
{% block title %}首页 - 我的网站{% endblock %}
{% block content %}
<h1>欢迎来到首页</h1>
<p>当前时间:{{ current_time | datetimeformat}}</p>
{% endblock %}
- 渲染结果:

3.3 组件化开发
模板继承支持组件化开发。你可以将页面的不同部分定义为独立的模板块,然后在子模板中组合这些块。这种方式可以提高代码的可维护性和可复用性。
- Flask后端代码:
# -*- coding: utf-8 -*-
from flask import Flask, render_template
from datetime import datetime
app = Flask(__name__)
# 定义自定义过滤器
def datetimeformat(value, format='%Y-%m-%d %H:%M:%S'):
return value.strftime(format)
# 注册过滤器
app.jinja_env.filters['datetimeformat'] = datetimeformat
@app.route('/')
def index():
return render_template('index.html')
@app.route('/about')
def aboutx():
return render_template('about.html')
if __name__ == '__main__':
app.run()
- 父模板(base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}默认标题{% endblock %}</title>
</head>
<body>
<header>
<h1>头部header</h1>
<h1>我的网站,我来自父模板</h1>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于父模板</a></li>
</ul>
</nav>
</header>
<main>
{% block content %}
<p>这是默认内容。</p>
{% endblock %}
</main>
<footer>
<h1>尾部footer</h1>
<p>© 2025 我的网站</p>
</footer>
</body>
</html>
- 子模板-1(index.html):
{% extends "base.html" %}
{% block title %}首页 - 我的网站{% endblock %}
{% block content %}
<h1>关于我们,子模板-1的网站</h1>
<p>这里是关于我们页面的内容。</p>
{% endblock %}
- 子模板-2(about.html):
{% extends "base.html" %}
{% block title %}关于我们 - 我的网站{% endblock %}
{% block content %}
<h1>关于我们,子模板-2的网站</h1>
<p>这里是关于我们页面的内容。</p>
{% endblock %}
- 渲染结果:

四、结束语
通过本文的介绍,你已经掌握了 Jinja2 模板的继承机制,并学会了如何在实际项目中应用模板继承。模板继承不仅可以减少模板代码的重复,还可以提高代码的可维护性和可复用性。希望这些知识能够帮助你在 Flask 开发中更加高效地构建高质量的 Web 应用。
如果你对 Jinja2 模板继承有更多问题,或者在实际开发中遇到了困难,欢迎在评论区留言,我会尽力为你解答。
最后,感谢你的阅读!如果你觉得本文对你有帮助,不妨点赞和关注,我会继续分享更多关于 Python 和 Flask 开发的实用知识。🚀
关注专栏,每周更新,带你从“第一个 Flask 项目”一路进阶到“Docker 部署、JWT 鉴权、微服务拆分”。
版权归作者所有,未经许可请勿抄袭,套用,商用(或其它具有利益性行为)。
更多推荐


所有评论(0)