1.为了避免在每个视图函数中都使用重复的代码,Flask提供了注册通用函数的功能,注册的函数可在请求被分发到视图函数之前或之后调用。
请求钩子使用修饰器实现。Flask支持以下4种钩子:
- before_first_request:顾名思义,注册一个在处理第一个请求之前运行的函数。
- before_request:注册一个在处理请求之前运行的函数。
- after_request:注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行。
- teardown_request:注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行。
在请求钩子函数和视图函数之间共享数据一般使用上下文全局变量g。
2.源码
def before_request(self, f):
"""Registers a function to run before each request."""
self.before_request_funcs.append(f)
return f
def after_request(self, f):
"""Register a function to be run after each request."""
self.after_request_funcs.append(f)
return f
可以看到,两个函数都声明了基本功能,分别用到了self.before_request_funcs.append()和self.before_request_funcs.append()两种属性。So,继续深入。
#: a list of functions that should be called at the beginning
#: of the request before request dispatching kicks in. This
#: can for example be used to open database connections or
#: getting hold of the currently logged in user.
#: To register a function here, use the :meth:`before_request`
#: decorator.
self.before_request_funcs = []
#: a list of functions that are called at the end of the
#: request. Tha function is passed the current response
#: object and modify it in place or replace it.
#: To register a function here use the :meth:`after_request`
#: decorator.
self.after_request_funcs = []
看来,两者都是list(列表),同样使用append()添加注册函数。
def preprocess_request(self):
"""Called before the actual request dispatching and will
call every as :meth:`before_request` decorated function.
If any of these function returns a value it's handled as
if it was the return value from the view and further
request handling is stopped.
"""
for func in self.before_request_funcs:
rv = func()
if rv is not None:
return rv
在实际request前调用,会调用每个before_request装饰器函数。如果这些函数返回一个值,这个值像视图函数返回的值,那么上一个request处理就被停止。
遍历self.before_request_funcs列表,rv赋值为func(),如果rv存在,返回rv。
def process_response(self, response):
"""Can be overridden in order to modify the response object
before it's sent to the WSGI server. By default this will
call all the :meth:`after_request` decorated functions.
:param response: a :attr:`response_class` object.
:return: a new response object or the same, has to be an
instance of :attr:`response_class`.
"""
session = _request_ctx_stack.top.session
if session is not None:
self.save_session(session, response)
for handler in self.after_request_funcs:
response = handler(response)
return response
在被发送到WSGI服务之前,可以为了更改resounse_class类而覆盖。这种行为默认情况下将调用after_request装饰器函数。