Flask的上下文源码剖析

先写一段Flask程序

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.__call__  # 不加括号就不会调用,看源码方便
    app.run()  # 请求一旦到来,就执行app.__call__()方法

请求一旦到来,就会执行app.__call__()方法,我们先看__call__的源码。

    def __call__(self, environ, start_response):
        """The WSGI server calls the Flask application object as the
        WSGI application. This calls :meth:`wsgi_app` which can be
        wrapped to applying middleware."""
        return self.wsgi_app(environ, start_response)

这段代码中的注释翻译过来是这样的:WSGI服务器调用Flask应用程序对象作为WSGI应用程序。这就叫: meth : ` wsgi _ app ',它可以打包应用中间件。"

这里面有envirron和start_response参数,是WSGI传过来的,传过来就处理好。然后看下一步,点击wsgi_spp看源码

    def wsgi_app(self, environ, start_response):

        ctx = self.request_context(environ)  # 并且又处理了一次environ
        error = None

wsgi_app方法里面有一个ctx变量,这里面的request_context里面封装了很多方法,里面一个是处理request,一个处理session的。并且又处理了一次environ。

看request_context的源码。

    def request_context(self, environ):

        return RequestContext(self, environ)

它里面返回了一个RequestContext(self, enveron)对象。

看RequestContext源码

class RequestContext(object):

    def __init__(self, app, environ, request=None):  # 这里面的envieon是不太彻底的请求
        self.app = app
        if request is None:  # 看着一句条件,看参数request=None,满足条件
            request = app.request_class(environ)  # 如果request=None就走这一行,把原生的请求给它,让他继续加工
        self.request = request  # 看到这就知道了前面的ctx.request就等于Request(environ)这个对象
        self.url_adapter = app.create_url_adapter(self.request)
        self.flashes = None
        self.session = None  # ctx.session = None
        self._implicit_app_ctx_stack = []
self.preserved = False
self._preserved_exc = None
self._after_request_functions = []
self.match_request()

它里面有environ参数和request参数。看里面的if语句,如果参数request是空,就把原生的请求给request_class这个类继续加工。

里面还有一个self.session,并且是空的。所以ctx.request就等于Request(environ)这个对象,ctx.session = None。

并且ctx = self.request_context(environ)这一行代码不仅创建了一个对象,还实现了一个路由匹配,因为init里面还有一行代码self.match_request(),这个就是通过路由来找视图函数,这里就不多说了。

综上所述request.context就是封装了处理request和session的方法。

猜你喜欢

转载自www.cnblogs.com/aaronthon/p/9459897.html
今日推荐