一 .Flask请求流程
1. flask项目整个请求流程其实就是执行
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
以上就是请求相关的流程。总结:
- 先执行第一次请求之前函数,执行完之后后续请求中不再执行
- 再从上往下执行请求之前函数,如果有返回值,不再执行后面的请求之前函数,也不执行真正的视图函数
- 没有返回值时执行视图函数,再执行请求之后函数
- 请求之后函数必须要有参数,并且有返回值
- 请求之后函数是从下往上返回执行