一、钩子函数定义
钩子函数:是在一个事件触发的时候,捕获到它的数据,对他进行处理,再将处理后的数据返回
二、Flask常用的请求扩展
1、before_first_request
项目启动后第一次请求的时候执行
# 项目启动后,发起的第一次请求会走它 @app.before_first_request def first(): print('第一次发起请求') return 'first_request请求'
2、before_request
每次请求来之前执行,类似于django的process_request,可以应用在校验用户的场景
注意:如果有多个before_request,执行顺序从上往下,如果多个before_request有一个return 返回值,那么它接下来的before_request以及它装饰的视图函数将不会再执行
@app.before_request def login_d(): #如果没有cookies值,则跳转到登陆界面重新登陆 cookies=request.cookies if cookies is None: return redirect('/login') else: return '我来了,请开门' @app.before_request def login_d1(): print('我来了1') return '我来了1,请开门' # 注意:before_request是从上往下执行,第一个有return返回值,所以第二个before_request不会再走
3、after_reqeust
每次请求后执行,如果请求出现异常,则不会执行,类似Django的process_response,执行顺序是从下往上
@app.after_request def after(response): print('我走了') return response @app.after_request def after1(response): print('我走了1') return response # 注意:是先执行after1再执行after,因为它的执行顺序是从下往上
4、teardown_request
视图函数执行完,都会走它,一般用来记录错误日志,如下例子,index页面出错了,它捕获到错误e
注意:必须用带参数,参数可以自定义
# 视图函数执行完会走它,一般用来记录出错日志 @app.teardown_request def tear(e): print(e) print('我关门了') @app.route('/index') def index(): print('aaa') ad return 'test'
5、errorhandler监听错误状态码
通过监听http错误状态码(也就是4和5系列的状态码),进监听的状态码进行处理
@app.errorhandler(400) def status(error): print(error) return 'http 400错误'
6、template_global全局模板标签
@app.template_global() def add(a,b): return a+b # 前端调用 {{add(1,2)}}
7、template_filter全局过滤器
@app.template_filter() def add_filter(a1, a2, a3): return a1 + a2 + a3 # 前端调用 {{1|add_filter(2,3,4)}}
总结:有了全局过滤器和模板标签,就不用再传一个函数给模板调用了。before_request和after_request跟Django的process_request和process_response中间,本质基本一样
三、中间件
本质:就是重写app的__call__方法,还是调用原来的app.wsgi_app方法,只不过是在调用wsgi_app方法前后添加一些自己的代码功能
创建中间件类过程:先创建一个中间件类,通过__init__初始化,将wsgi_app处理成中间件类的属性,再重写__call__方法,再__call__方法中书写中间件代码,将__call__方法的参数传给属性wsgi_app(*args,**kwargs)。
使用: 将中间件类实例化的对象,赋值给app.wsgi_app
注意,一定要把原来的app.wsgi_app方法传给中间件类初始化
重写的__call__方法本质还是在执行原来的call方法,只不过是在执行wsgi_app方法前后,添加一些自定制的代码
例子
from flask import Flask app=Flask('__name__') class Mindle(object): def __init__(self,wsgi_app): self.wsgi_app=wsgi_app def __call__(self, *args, **kwargs): ''' 这里书写中间件代码,还没对请求处理的时候 ''' obj=self.wsgi_app(*args,**kwargs) ''' 这里书写中间件代码,请求处理好的时候 ''' return obj if __name__=='__main__':
# 将原来的app.wsgi_app方法传给Midle中间件类,实例化成类的属性 app.wsgi_app=Mindle(app.wsgi_app) app.run()