【11天从零基础入门flask】第 6 章:模板优化
第 6 章:模板优化
在本章中,我们将学习如何优化 Flask 应用中的模板,解决重复代码问题,使得模板更加清晰、易于维护,并提高开发效率。
6.1 自定义错误页面
Flask 提供了默认的错误页面,例如 404 错误(页面未找到)。但这些默认的错误页面非常简陋,不能提供用户友好的体验。在实际开发中,我们通常需要根据需求自定义错误页面。
1. 编写 404 错误页面模板
首先,我们可以为应用编写一个自定义的 404 错误页面。假设用户访问一个不存在的 URL(例如 /hello
),Flask 默认会返回一个简单的 404 错误页面,我们可以通过自定义模板来使页面更加友好。
在 templates
文件夹中创建一个 404.html
文件,内容如下:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>{{ user.name }}'s Watchlist</title><link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">
</head>
<body><h2><img alt="Avatar" class="avatar" src="{{ url_for('static', filename='images/avatar.png') }}">{{ user.name }}'s Watchlist</h2><ul class="movie-list"><li>Page Not Found - 404<span class="float-right"><a href="{{ url_for('index') }}">Go Back</a></span></li></ul><footer><small>© 2018 <a href="http://helloflask.com/book/3">HelloFlask</a></small></footer>
</body>
</html>
2. 注册错误处理函数
使用 @app.errorhandler
装饰器来注册一个错误处理函数。当发生 404 错误时,这个函数会被触发,返回自定义的错误页面。
@app.errorhandler(404)
def page_not_found(e):user = User.query.first()return render_template('404.html', user=user), 404
通过 render_template('404.html', user=user)
,我们将 user
变量传递给模板,使得页面可以显示用户信息。
现在,当用户访问一个不存在的 URL 时,Flask 会显示我们自定义的错误页面。
6.2 模板上下文处理函数
重复代码是开发中常见的挑战,尤其是像 user
这样的全局变量,需要在多个模板中使用。在 Flask 中,可以使用 上下文处理函数 来自动注入这些变量到每个模板中,避免在每个视图函数中重复传递相同的变量。
1. 创建上下文处理函数
我们使用 @app.context_processor
装饰器注册一个模板上下文处理函数,该函数返回一个字典,字典中的键值对将被自动传递到每个模板中。
@app.context_processor
def inject_user():user = User.query.first()return dict(user=user)
通过这种方式,我们无需在每个视图函数中传递 user
变量,它会自动注入到每个模板中。
2. 修改视图函数
现在,我们可以删除视图函数中的 user
变量,Flask 会自动将 user
变量注入到模板中:
@app.errorhandler(404)
def page_not_found(e):return render_template('404.html'), 404@app.route('/')
def index():movies = Movie.query.all()return render_template('index.html', movies=movies)
这简化了代码,减少了重复工作。
6.3 使用模板继承组织模板
Flask 使用 Jinja2 作为模板引擎,它提供了 模板继承 机制,使得我们能够创建一个通用的基模板,在子模板中重用代码,从而避免重复的 HTML 结构。
1. 创建基模板
基模板通常包含应用的公共部分,如导航栏、页脚和页面头部。我们将在 templates
文件夹中创建一个 base.html
文件。
<!DOCTYPE html>
<html lang="en">
<head>{% block head %}<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{{ user.name }}'s Watchlist</title><link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">{% endblock %}
</head>
<body><h2><img alt="Avatar" class="avatar" src="{{ url_for('static', filename='images/avatar.png') }}">{{ user.name }}'s Watchlist</h2><nav><ul><li><a href="{{ url_for('index') }}">Home</a></li></ul></nav>{% block content %}{% endblock %}<footer><small>© 2018 <a href="http://helloflask.com/book/3">HelloFlask</a></small></footer>
</body>
</html>
在 base.html
中,我们定义了 head
和 content
块,这些块将在子模板中被覆盖或填充。
2. 创建子模板
子模板将继承 base.html
,并覆盖 content
块以插入特定内容。我们将 index.html
模板修改为:
{% extends 'base.html' %}{% block content %}
<p>{{ movies|length }} Titles</p>
<ul class="movie-list">{% for movie in movies %}<li>{{ movie.title }} - {{ movie.year }}<span class="float-right"><a class="imdb" href="https://www.imdb.com/find?q={{ movie.title }}" target="_blank" title="Find this movie on IMDb">IMDb</a></span></li>{% endfor %}
</ul>
<img alt="Walking Totoro" class="totoro" src="{{ url_for('static', filename='images/totoro.gif') }}" title="to~to~ro~">
{% endblock %}
通过 {% extends 'base.html' %}
,子模板继承了基模板的结构,并在 content
块中插入电影列表。
3. 404 错误页面模板
错误页面也可以使用继承来减少重复代码。例如,我们将 404.html
修改为:
{% extends 'base.html' %}{% block content %}
<ul class="movie-list"><li>Page Not Found - 404<span class="float-right"><a href="{{ url_for('index') }}">Go Back</a></span></li>
</ul>
{% endblock %}
通过模板继承,我们避免了在每个页面中重复编写头部、导航栏和页脚的 HTML 代码。
6.4 添加 IMDb 链接
为了进一步优化我们的页面,我们为每个电影条目添加了一个 IMDb 链接,允许用户快速查看电影的详细信息。
<span class="float-right"><a class="imdb" href="https://www.imdb.com/find?q={{ movie.title }}" target="_blank" title="Find this movie on IMDb">IMDb</a>
</span>
CSS 样式如下:
.float-right {float: right;
}.imdb {font-size: 12px;font-weight: bold;color: black;text-decoration: none;background: #F5C518;border-radius: 5px;padding: 3px 5px;
}
通过这些优化,我们的主页更加美观且功能丰富。
6.5 本章小结
在本章中,我们学习了如何优化 Flask 模板,解决重复代码的问题。通过自定义错误页面、使用模板上下文处理函数、模板继承等技巧,我们使得模板更加清晰和易于维护。这样做不仅提高了开发效率,也让代码更加简洁。
进阶提示
-
错误页面的进一步优化:除了 404 错误页面,你还可以为 400 和 500 错误创建自定义页面,这样可以为用户提供更好的错误处理体验。
-
模板优化技巧:通过模板继承和上下文处理函数,可以减少重复代码和提高模板的可复用性。对于复杂的应用,确保模板的组织结构清晰合理。
-
动态链接:在实际项目中,IMDB 链接可能需要更复杂的查询,支持多个数据源(如豆瓣、时光网等)。你可以根据需求动态生成这些链接,增强用户体验。
通过本章的学习,你已经掌握了 Flask 模板优化的技巧,下一章将介绍如何处理用户表单输入,进一步完善应用的功能。