Python-Flask入门及路由基础请参看Python-Flask入门,路由route、项目启动、修改网址端口、获取URL地址和参数、Form数据_无敌路路帅气的博客-CSDN博客
本节重点讲述静态文件、页面跳转、错误信息和动态网页模板。
#1、静态文件
利用Pycharm生成Flask项目会自动创建一个static文件夹,用于存放静态文件。
静态文件一般可以是:
- CSS层叠样式表,用于动态Web应用。
- JavaScript文件,用于开发前端Web页面。
- 真正的静态文件,如txt、jpg、logo图片等。

1.1 访问一个含有CSS样式表单的静态网页
(1)我们首先在/static文件夹下创建一个CSS样式C1-1.CSS,如上图所示。
h5{color:green;font-size:25px;}
p{color:darkgreen;font-size: 18px;font-family: 宋体, serif;font-weight: bold}
(2)我们再在templates文件夹下创建一个staticdemo.html,代码如下:
{{ url_for('static',filename='C1-1.CSS') }}表示样式表单来源于staitc文件夹下面的C1-1.CSS。
url_for()有重定向和指向作用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>staticdemo</title>
<link rel="stylesheet" href="{{ url_for('static',filename='C1-1.CSS') }}">
</head>
<body>
<h5>静态文件</h5>
<p>动态的 web 应用也需要静态文件,一般是 CSS 和 JavaScript 文件。理想情况下你的 服务器已经配置好了为你的提供静态文件的服务。但是在开发过程中, Flask 也能做好 这项工作。只要在你的包或模块旁边创建一个名为 static 的文件夹就行了。 静态文件位于应用的 /static 中。</p>
</body>
</html>
(3)我们最后在app.py中创建访问接口路由,直接返回 staticdemo.html网页。
使用 render_template() 方法可以渲染网页模板,这里表示直接返回网页。
from flask import render_template
@app.route('/staticdemo')
def show_static_css():
return render_template("staticdemo.html")
(4)启动项目,输入http://127.0.0.1:5000/staticdemo ,则会显示我们配置好的含有CSS样式表单的静态网页,效果如下:

1.2 访问静态文件接口路由,直接返回静态文件
使用send_file(静态文件路径) ,可以直接返回静态文件,如下例,我们在static文件夹下拷贝一个python.jpg,我们使用send_file('./static/python.jpg')可以直接将python.jpg返回并显示在网页中。
from flask import send_file
@app.route('/staticfile')
def show_static_file():
return send_file('static/python.jpg')
启动项目,输入http://127.0.0.1:5000/staticfile ,则会在网页中显示该图片,效果如下:

#2、 页面跳转
使用 redirect() 函数可以重定向,实现页面跳转功能。
这里一般有两种方法,第一种是通过 redirect(“/新的路由”) 直接跳转到新的接口路由,第二种是利用 redirect( url_for(“新的路由对应函数” )) 跳转到相应路由的函数。
第一种方式代码如下例,当我们 http://127.0.0.1:5000/call,访问/call接口时,则自动跳转到/newcall接口,即返回/newcall接口值。
from flask import redirect
#直接跳转到新的路由
@app.route('/call')
def show_call():
return redirect("/newcall")
@app.route('/newcall')
def new_call_function():
return "this is new call"

第二种方式代码如下例,通过 url_for(“新的路由对应函数” ) 实现页面跳转,效果同上。
from flask import redirect
#通过 url_for(“新的路由对应函数” ) 实现页面跳转
@app.route('/call')
def show_call():
return redirect(url_for("new_call_function"))
@app.route('/newcall')
def new_call_function():
return "this is new call"
#3、 错误信息
3.1 使用 abort() 函数可以及时退出请求,并返回错误代码。
如下例,我们设置 abort(401),即权限错误,禁止访问,系统会返回错误信息。
from flask import abort
@app.route('/abort')
def show_abort():
abort(401)
当我们访问 http://127.0.0.1:5000/abort 时,系统返回401错误信息。

缺省情况下每种出错代码都会对应显示一个黑白的出错页面。
这时使用 errorhandler() 装饰器可以自定义出错页面。
@app.errorhandler(401)
def error_401(error):
return "错误访问!<br>错误信息:%s" %error
当我们再次访问访问 http://127.0.0.1:5000/abort 时,系统返回我们自定义的报错页面。

我们还可以单独定义一个静态网页用来显示错误信息, 并通过 render_template() 函数指向该页面,如下例,我们先在templates文件夹下创建一个静态网页page_unauthorized.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>禁止访问页面</title>
</head>
<body>
<table cellspacing="0" border="1" bgcolor="#f2f2f2" width="400px">
<caption>错误的页面</caption>
<tr><th>错误代码</th><th>错误信息</th>></tr>
<tr><th>401</th><th>权限错误,禁止访问!</th>></tr>
</table>
</body>
</html>
接下来创建错误接口路由,代码如下:
from flask import render_template
@app.route('/abort')
def show_abort():
abort(401)
@app.errorhandler(401)
def error_401(error):
return render_template("page_unauthorized.html")
当我们再次访问/abort接口时,则显示我们自定义的错误页面。

3.2 定义通用异常处理器,返回json错误信息
我们可以定义HTTP通用异常处理器,将所有捕获的异常输出,这时我们需要使用HTTPException基类甚至是 Exception基类。
我们将异常信息转化为json字符串写入response.data中最后返回,如下例:
from flask import json
from werkzeug.exceptions import HTTPException
@app.errorhandler(HTTPException)
def handle_exception(e):
# 设置reponse返回信息
response = e.get_response()
# 将报错信息转化为json字符串,ensure_ascii = False确保中文不会乱码
response.data = json.dumps({
"状态码": e.code,
"错误信息": e.name,
"错误描述": e.description,
},ensure_ascii = False)
response.content_type = "application/json"
return response
启动项目,当我们访问一个不存在的路由时 http://127.0.0.1:5000/any,则会输出404报错json信息。

#4、 动态网页模板
- Flask 自动配置 Jinja2 模板引擎。
- Flask 会在 templates 文件夹内寻找模板。
- Flask 使用 render_template() 方法渲染模板。
- 我们只需要提供模板名称,将参数传递给模板的变量就行了。
例1,我们获取网址中的变量传递给动态网页模板:
我们首先在templates文件夹中创建一个动态网页模板mod1.html。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello mod1</title>
</head>
<body>
{% if name %}
<h3>Hello {{ name }}</h3>
{% else %}
<h3>Hello world</h3>
{% endif %}
</body>
</html>
接下来在app,py中创建动态网页接口路由。
from flask import render_template
@app.route("/mod1")
@app.route("/mod1/<string:name>")
def show_mod1(name=None):
return render_template("mod1.html",name = name)
最后启动项目,访问 http://127.0.0.1:5000/mod1/lulu ,变量 lulu 已经传递到 mod1.html 动态网页中。

当我们不输入变量,直接访问 http://127.0.0.1:5000/mod1 ,则会返回Hello world。
例2,我们将多行数据传递给动态网页模板表格中。
我们首先在template文件夹中创建一个动态网页模板mybook,html。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My book</title>
</head>
<body>
<table cellspacing="0" align="center" bgcolor="#f2f2f2" width="600px" border="1">
<caption>MY BOOKS</caption>
<tr><th>书名</th><th>作者</th><th>价格</th></tr>
{% if books %}
{% for book in books %}
<tr><td>{{ book[0] }}</td><td>{{ book[1] }}</td><td>{{ book[2] }}</td></tr>
{% endfor %}
{% endif %}
</table>
</body>
</html>
接下来在app,py中创建数据和网页接口路由。
@app.route("/mod2")
def show_mod2():
#books模拟数据库取值,为Tuple元组集合格式
books = (('红楼梦', '曹雪芹', 29.5),
('西游记', '吴承恩', 15.8),
('三国演义', '罗贯中', 30.0),
('水浒传', '施耐庵', 26.58),
('聊斋志异', '蒲松龄', 18.0))
return render_template("mybook.html",books=books)
最后启动项目,访问 http://127.0.0.1:5000/mod2 ,返回动态网页表格。

例3,进阶:模板继承,实现动态网页模块式开发。
Jinja 最强大的部分是模板继承。模板继承允许我们构建一个基本“骨架”模板,该模板包含我们网站的所有常见元素并定义子模板可以覆盖的块。
(1)我们从一个简单的例子开始。首先我们定义一个基础模板 base.html,该模板是一个简单的 HTML 框架,我们可以将它用于一个简单的两栏页面。内容填充是“子”模板的工作。
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="UTF-8">
<title>{% block title %}{% endblock %} - 我的网页</title>
{% endblock %}
</head>
<body>
<div id="content">
{% block content %}{% endblock %}
</div>
<div id="footbar">
{% block footbar %}
©Copyright Python Flask by <a href="https://flask.palletsprojects.com" target="_blank">link</a>{% endblock %}
</div>
</body>
</html>
上述例子中,标签定义了四个子模板可以填充的块。块标签所做的只是告诉模板引擎子模板可以覆盖模板中的那些占位符。{% block %}
(2)接下来我们创建子模版 index.html,该模板通过 {% extends "base.html" %} 继承了基础模板的内容(我们称之为父模板),在访问时,如是父模板的内容则会直接调用相关块内容;如是子模块没有定义的块,如 foot 块,则会使用父模板的值。
{% extends "base.html" %}
{% block title %}子网页{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.single{color: darkred}
</style>
{% endblock %}
{% block content %}
<h3>首页</h3>
<p class="single">欢迎来到我的Flask动态网页</p>
{% endblock %}
{{ super() }} 是超级块,将返回父模板相应块的全部内容。
(3)最后我们创建一个接口路由,渲染并跳转到子模版即可。
from flask import render_template
@app.route("/mod3")
def show_mod3():
return render_template("index.html")
(4)启动项目,访问 http://127.0.0.1:5000/mod3 ,返回子模版并继承父模板内容,实现模板继承。
更多 jinjia2 动态模板教程,请参看官方文档。Template Designer Documentation — Jinja Documentation (3.1.x)
https://jinja.palletsprojects.com/en/3.1.x/templates/