08-Flask高级
01 请求扩展
01 before_first_request :项目启动后第一次请求的时候执行
@app.before_first_request
def before_first_request():
print('第一次请求的时候执行')
02 before_request:每次请求之前执行
@app.before_request
def before_request():
print('每次请求之前执行')
# return '直接return' # 如果有一个写了return返回值,那么其他的before_request不会执行,视图也不会执行。
注意:
-
可以写多个
-
如果有一个写了return返回值,那么其他的before_request不会执行,视图也不会执行。
03 after_request:每次请求之后执行,请求出现异常不会执行
def after_request(result):
print('每次请求之后执行,请求出现异常不会执行')
# 这个result是封装的响应对象,需要return否则报错
return result
04 errorhandler:可以自定义监听响应的状态码并处理:
@app.errorhandler(404)
def errorhandler(error):
print(error) # 是具体的错误信息
return '404页面跑到了火星上面去了'
@app.errorhandler(500)
def errorhandler(error):
print('errorhandler的错误信息')
print(error)
return '服务器内部错误500'
05 teardown_request:每次请求之后绑定了一个函数,在非debug
模式下即使遇到了异常也会执行。
@app.teardown_request
def terardown_reqquest(error):
print('无论视图函数是否有错误,视图函数执行完都会执行')
print('想要此函数生效,debug不能为True')
print('error 是具体的错误信息')
print(error)
06 template_global():全局模板标签
@app.template_global()
def add(a1, a2):
return a1+a2
#{{add(1,2)}}
这个可以在模板中作为全局的标签使用,在模板中可以直接调用,调用方式:
{{add(1,2)}}
07 template_filter:全局模板过滤器
@app.template_filter()
def add_filter(a1, a2, a3):
return a1 + a2 + a3
这个可以在模板中作为全局过滤器使用,在模板中可以直接调用,调用方式(注意同template_global的区别) :
{{1|add_filter(2,3,4)}}
优势:
全局模板标签和全局模板过滤器简化了需要手动传一个函数给模板调用:
# app.py
```
def test(a1,a2):
return a1+a2
@app.route('/')
def index():
return render_template('index.html',test=test)
```
# index.html
```
{{test(22,22)}}
```
02 flask中间件
Flask的中间件的性质,就是可以理解为在整个请求的过程的前后定制一些个性化的功能。
flask的中间件的实现案例:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
print('视图函数中')
return 'hello world'
class my_middle:
def __init__(self,wsgi_app):
self.wsgi_app = wsgi_app
def __call__(self, *args, **kwargs):
print('中间件的代码上')
obj = self.wsgi_app( *args, **kwargs)
print('中间件的代码下')
return obj
if __name__ == '__main__':
app.wsgi_app = my_middle(app.wsgi_app)
# app.wsgi_app(environ, start_response)
app.run()
# 梳理一下 根据werkzeug我们可以知道 每次请求必然经历了app()
# 所以我们要查看Flask的源码找到__call__方法
# 找到了__call__方法后发现执行了return self.wsgi_app(environ, start_response)
# 然后flask里面所有的内容调度都是基于这个self.wsgi_app(environ, start_response),这就是就是flask的入口
# 如何实现中间件呢? 原理上就是重写app.wsgi_app,然后在里面添加上一些自己想要实现的功能。
# 首先分析 app.wsgi_app需要加括号执行 所以我们把app.wsgi_app做成一个对象,并且这个对象需要加括号运行
# 也就是会触发这个对象的类的__call__()方法
# 1 那么就是app.wsgi_app=对象=自己重写的类(app.wsgi_app) ,我们需要在自己重写的类里面实现flask源码中的app.wsgi_app,在实例化的过程把原来的app.wsgi_app变成对象的属性
# 2 app.wsgi_app() =对象() = 自己重写的类.call()方法
# 3 那么上面的代码就可以理解了,在自己重写的类中实现了原有的__call__方法
梳理:
-
根据
werkzeug
我们可以知道 每次请求必然经历了app()
-
所以我们要查看Flask的源码找到
__call__
方法 -
找到了Flask的
__call__
方法后发现执行了return self.wsgi_app(environ, start_response)
-
flask里面所有的内容调度都是基于这个
self.wsgi_app(environ, start_response)
,这就是就是flask
的入口,也就是selef是app,也就是app.wsgi_app(environ, start_response)
为程序的入口。 -
如何实现中间件呢? 原理上就是重写app.wsgi_app,然后在里面添加上一些自己想要实现的功能。
-
首先分析 app.wsgi_app需要加括号执行 所以我们把app.wsgi_app做成一个对象,并且这个对象需要加括号运行。
-
也就是会触发这个对象的类的
__call__()
方法。
实操理解:
-
app.wsgi_app=对象=自己重写的类(app.wsgi_app)
提示:我们需要在自己重写的类里面实现flask源码中的app.wsgi_app,在实例化的过程把原来的 app.wsgi_app变成对象的属性
-
app.wsgi_app() =对象() = 自己重写的类.call()方法
app.wsgi_app(实参) =对象(实参) = 自己重写的类.call(实参)方法
-
那么上面的代码就可以理解了,在自己重写的类中实现了原有的call方法,并且重新调用了原有的app.wsgi_app
03 蓝图:
3.1 蓝图的基本使用
在我的flask中,我们可以利用蓝图对程序目录的划分。
思考如果我们有很多个视图函数,比如下面这样我们是不是应该抽取出来专门的py文件进行管理呢?