zoukankan      html  css  js  c++  java
  • Flask快速入门(11) — 请求流程


    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
    

    (2)@before_request:将请求之前函数放入self.before_request_funcs列表中

    def before_request(self, f):
        self.before_request_funcs.setdefault(None, []).append(f)
        return f
    

    (3)@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():请求之前

    def 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
    

    以上就是请求相关的流程。总结:

    • 先执行第一次请求之前函数,执行完之后后续请求中不再执行
    • 再从上往下执行请求之前函数,如果有返回值,不再执行后面的请求之前函数,也不执行真正的视图函数
    • 没有返回值时执行视图函数,再执行请求之后函数
    • 请求之后函数必须要有参数,并且有返回值
    • 请求之后函数是从下往上返回执行
  • 相关阅读:
    CSS3 not
    rxjs1
    Angular 2 组件之间如何通信?
    开发去。。
    补零补零
    MySQL数据库从复制及企业配置实践
    互联网中接口安全解决方案
    redis服务打不开--解决办法
    搭建Git服务器
    git将当前分支上修改的东西转移到新建分支
  • 原文地址:https://www.cnblogs.com/863652104kai/p/11687747.html
Copyright © 2011-2022 走看看