flask 项目整个请求流程其实就是执行: wsgi_app() 方法中调用的 full_dispatch_request(), 包括请求扩展和真正的视图函数
- full_dispatch_request()
- def full_dispatch_request(self):
- # 执行 before_first_request 函数
- self.try_trigger_before_first_request_functions()
- try:
- # 发送请求开始信号
- request_started.send(self)
- # 执行请求之前函数
- rv = self.preprocess_request()
- # 如果请求之前函数没有返回值, 执行请求函数
- if rv is None:
- rv = self.dispatch_request()
- except Exception as e:
- rv = self.handle_user_exception(e)
- # 执行请求之后函数
- return self.finalize_request(rv)
在分析这段代码之前, 先回顾下请求扩展函数
(1)@App.before_first_request: 就是将第一次请求之前的函数刚入 self.before_first_request_funcs 列表中
- def before_first_request(self, f):
- self.before_first_request_funcs.append(f)
- return f
@before_request: 将请求之前函数放入 self.before_request_funcs 列表中
- def before_request(self, f):
- self.before_request_funcs.setdefault(None, []).append(f)
- return f
@after_request: 将请求之后函数放在 self.after_request_funcs 列表中
- def after_request(self, f):
- self.after_request_funcs.setdefault(None, []).append(f)
- return f
1. try_trigger_before_first_request_functions(): 第一次请求之前
- def try_trigger_before_first_request_functions(self):
- if self._got_first_request: # 初始为 False
- return
- with self._before_request_lock:
- if self._got_first_request:
- return
- for func in self.before_first_request_funcs:
- func()
- self._got_first_request = True
将 self.before_first_request_funcs 也就是第一次请求前函数一个个取出执行. 执行完后将 self._got_first_request 设为 True. 这样在后面的请求中就不再执行, 也就是说只在第一次请求之前执行
2. self.preprocess_request(): 请求之前
- ef preprocess_request(self):
- bp = _request_ctx_stack.top.request.blueprint
- funcs = self.url_value_preprocessors.get(None, ())
- if bp is not None and bp in self.url_value_preprocessors:
- funcs = chain(funcs, self.url_value_preprocessors[bp])
- for func in funcs:
- func(request.endpoint, request.view_args)
- funcs = self.before_request_funcs.get(None, ())
- if bp is not None and bp in self.before_request_funcs:
- funcs = chain(funcs, self.before_request_funcs[bp])
- # 将请求之前函数遍历取出执行
- for func in funcs:
- rv = func()
- # 如果请求之前函数有返回值, 则返回, 下面的请求之前函数不再执行
- if rv is not None:
- return rv
3. self.dispatch_request(): 请求
- def dispatch_request(self):
- req = _request_ctx_stack.top.request
- if req.routing_exception is not None:
- self.raise_routing_exception(req)
- rule = req.url_rule
- if (
- getattr(rule, "provide_automatic_options", False)
- and req.method == "OPTIONS"
- ):
- return self.make_default_options_response()
- # 执行真正的视图函数
- return self.view_functions[rule.endpoint](**req.view_args)
4.finalize_request(): 请求之后
- def finalize_request(self, rv, from_error_handler=False):
- # 先 make_response 响应
- response = self.make_response(rv)
- try:
- # 执行请求之后函数
- response = self.process_response(response)
- # 发送请求结束信号
- request_finished.send(self, response=response)
- except Exception:
- if not from_error_handler:
- raise
- self.logger.exception(
- "Request finalizing failed with an error while handling an error"
- )
- # 将响应返回
- return response
- def process_response(self, response):
- ctx = _request_ctx_stack.top
- bp = ctx.request.blueprin
- funcs = ctx._after_request_functions
- # reversed 将请求之后函数列表进行了反转
- if bp is not None and bp in self.after_request_funcs:
- funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
- if None in self.after_request_funcs:
- funcs = chain(funcs, reversed(self.after_request_funcs[None]))
- # 便利执行反转后的函数列表中的请求之后函数
- for handler in funcs:
- # 注意参数中有个 response, 所以我们的请求之后函数必须要有个参数. 并且要有返回值
- response = handler(response)
- if not self.session_interface.is_null_session(ctx.session):
- self.session_interface.save_session(self, ctx.session, response)
- return response
以上就是请求相关的流程. 总结:
先执行第一次请求之前函数, 执行完之后后续请求中不再执行
再从上往下执行请求之前函数, 如果有返回值, 不再执行后面的请求之前函数, 也不执行真正的视图函数
没有返回值时执行视图函数, 再执行请求之后函数
请求之后函数必须要有参数, 并且有返回值
请求之后函数是从下往上返回执行
来源: http://www.bubuko.com/infodetail-3259481.html