本文介绍一下蓝图的钩子,不要感到奇怪,Blueprint是为了能够在大型应用中对众多业务模块进行API分层次管理,因此一个blueprint也有使用钩子的必要。
蓝图的钩子和app的钩子,联系非常紧密,首先,我们看一下,app的钩子都存储在哪里了,以before_request为例
@app.before_request
def app_before_request():
print('app_before_request')
跟踪代码,看一下before_request的源码
@setupmethod
def before_request(self, f):
self.before_request_funcs.setdefault(None, []).append(f)
return f
app的钩子被注册在了app的before_request_funcs里,现在,看一下蓝图的before_request
@blue.before_request
def add_blue_before_request():
print('只在蓝图内生效')
跟踪代码,看一下蓝图的before_request源码
def before_request(self, f):
self.record_once(
lambda s: s.app.before_request_funcs.setdefault(self.name, []).append(f)
)
return f
同app的钩子一样,也存储在app的before_request_funcs里,它是一个字典,app的钩子存储时以None做key,蓝图的钩子存储时,以蓝图的名称做key,这就是他们的不同。
先来看后三个名称里有app的,这三个钩子装饰器,完全等同于于app的before_request, after_request和before_first_request,这三个装饰器将钩子函数注册到app.before_request_funcs里,用None做key。这样安排,是为了在各个蓝图里,可以对全局的请求做一些处理前后的操作。
既然蓝图的before_app_request等于app的before_request, 那么蓝图自身的before_request装饰器有什么用呢? before_request,after_request,teardown_request 蓝图的这3个钩子都只在蓝图内生效,请求如果不在蓝图的处理范围内,这些钩子函数不会被执行。如此,每个蓝图的可以只针对自身的请求做一些个性化的处理,而不会影响到其他蓝图。
最后说teardown_appcontext, 它等价于app的teardown_appcontext, 作用范围是整个app。
下表是蓝图钩子的生效范围
装饰器 | 生效范围 |
---|---|
before_request | 蓝图 |
after_request | 蓝图 |
teardown_request | 蓝图 |
teardown_appcontext | 全局 |
before_app_request | 全局 |
after_app_request | 全局 |
before_app_first_request | 全局 |
第二小节里,讲解了蓝图钩子的生效范围,下面实际验证理论
from flask import Flask, Blueprint
app = Flask(__name__)
blue = Blueprint('user', __name__, url_prefix='/user')
@blue.before_app_request
def add_app_before_request():
print('整个app生效')
@blue.before_request
def add_blue_before_request():
print('只在蓝图内生效')
@blue.route('/info')
def info():
return '小明'
app.register_blueprint(blue)
@app.before_request
def app_before_request():
print('app_before_request')
@app.route('/')
def index():
return 'hello'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5500)
代码里,app和blue都使用before_request:
实际验证与理论推论一致。
app与蓝图的before_request究竟哪个先执行,与注册顺序无关,app的优先级高于蓝图,先执行app注册的钩子函数,后执行蓝图注册的钩子函数。
原文:
http://www.coolpython.net/flask_tutorial/basic/flask-blue-hook.html