Flask源码:app.py (三)视图函数到Response

#视图函数到Response
    
    def full_dispatch_request(self):
        #调用使用before_request方法添加的一系列扩展函数,可重载自定义函数处理
        self.try_trigger_before_first_request_functions()
        try:
            request_started.send(self)    #request_started信号
            rv = self.preprocess_request()#分发前调用,与蓝图相关
            if rv is None:
                rv = self.dispatch_request()    #分发给视图函数处理
            #rv就是视图函数处理的结果
        except Exception as e:
            rv = self.handle_user_exception(e)
        #将结果传入finalize_request,封装视图函数处理结果
        return self.finalize_request(rv)    

    def finalize_request(self, rv, from_error_handler=False):
        response = self.make_response(rv)    #封装response成response_class的一个实例
        try:
            #默认调用after_request方法添加的一系列扩展函数,可重载自定义函数处理
            response = self.process_response(response)
            request_finished.send(self, response=response)   #发送request_finished信号
        except Exception:
            if not from_error_handler:
                raise
            self.logger.exception(
                "Request finalizing failed with an error while handling an error"
            )
        return response
    
    def make_response(self, rv):
         """Convert the return value from a view function to an instance of
        :attr:`response_class`.
        将返回值转换成Wrappers.py的response类的实例

        :param rv: the return value from the view function. The view function
            must return a response. Returning ``None``, or the view ending
            without returning, is not allowed. The following types are allowed
            for ``view_rv``:
            可以返回如下类型
            ``str`` (``unicode`` in Python 2)#UTF-8的字符串
                A response object is created with the string encoded to UTF-8
                as the body.

            ``bytes`` (``str`` in Python 2)
                A response object is created with the bytes as the body.

            ``dict``
                A dictionary that will be jsonify'd before being returned.

            ``tuple``
                Either ``(body, status, headers)``, ``(body, status)``, or
                ``(body, headers)``, where ``body`` is any of the other types
                allowed here, ``status`` is a string or an integer, and
                ``headers`` is a dictionary or a list of ``(key, value)``
                tuples. If ``body`` is a :attr:`response_class` instance,
                ``status`` overwrites the exiting value and ``headers`` are
                extended.

            :attr:`response_class`
                The object is returned unchanged.

            other :class:`~werkzeug.wrappers.Response` class
                The object is coerced to :attr:`response_class`.

            :func:`callable`
                The function is called as a WSGI application. The result is
                used to create a response object.
        """
        
        status = headers = None

        # unpack tuple returns    #处理元组类型
        if isinstance(rv, tuple):
            len_rv = len(rv)

            # a 3-tuple is unpacked directly
            if len_rv == 3:
                rv, status, headers = rv
            # decide if a 2-tuple has status or headers
            elif len_rv == 2:
                if isinstance(rv[1], (Headers, dict, tuple, list)):
                    rv, headers = rv
                else:
                    rv, status = rv
            # other sized tuples are not allowed
            else:
                raise TypeError(
                    "The view function did not return a valid response tuple."
                    " The tuple must have the form (body, status, headers),"
                    " (body, status), or (body, headers)."
                )

        # the body must not be None    不能为空
        if rv is None:
            raise TypeError(
                "The view function did not return a valid response. The"
                " function either returned None or ended without a return"
                " statement."
            )

        # make sure the body is an instance of the response class
        if not isinstance(rv, self.response_class):
            #text_type,bytes,bytearray类型直接调用response_class实例化
            if isinstance(rv, (text_type, bytes, bytearray)):    
                # let the response class set the status and headers instead of
                # waiting to do it manually, so that the class can handle any
                # special logic
                rv = self.response_class(rv, status=status, headers=headers)    
                status = headers = None
            #dict类型封装
            elif isinstance(rv, dict):    
                rv = jsonify(rv)    #json/init.py里的封装方法
             #BaseResponse或可调用类型处理
            elif isinstance(rv, BaseResponse) or callable(rv):   
                # evaluate a WSGI callable, or coerce a different response
                # class to the correct type
                try:
                    rv = self.response_class.force_type(rv, request.environ)
                except TypeError as e:
                    new_error = TypeError(
                        "{e}\nThe view function did not return a valid"
                        " response. The return type must be a string, dict, tuple,"
                        " Response instance, or WSGI callable, but it was a"
                        " {rv.__class__.__name__}.".format(e=e, rv=rv)
                    )
                    reraise(TypeError, new_error, sys.exc_info()[2])
            #报错
            else:    
                raise TypeError(
                    "The view function did not return a valid"
                    " response. The return type must be a string, dict, tuple,"
                    " Response instance, or WSGI callable, but it was a"
                    " {rv.__class__.__name__}.".format(rv=rv)
                )

        # prefer the status if it was provided    可自定义状态码
        if status is not None:
            if isinstance(status, (text_type, bytes, bytearray)):
                rv.status = status
            else:
                rv.status_code = status

        # extend existing headers with provided headers    可自定义头部
        if headers:
            rv.headers.extend(headers)

        return rv
    """
    从full_dispatch_request函数返回后
    直接调用response类方法装入WSGI框架处理了(response就是Wrappers.py的response类)
    """
    def wsgi_app(self, environ, start_response):
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                ctx.push()
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:  # noqa: B001
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)
发布了23 篇原创文章 · 获赞 0 · 访问量 2013

猜你喜欢

转载自blog.csdn.net/qq_33913982/article/details/104256435