zoukankan      html  css  js  c++  java
  • f'lask源码

     上下文本质 

    1
    2
    3
    4
    5
    6
    7
    8
    - 当请求过来后,将请求相关数据添加到 Local()类中
        {
            线程或协程唯一标识:{"stack":[request]},
            线程或协程唯一标识:{"stack":[]},
            线程或协程唯一标识:{"stack":[]}
        }
    - 以后使用时 去读取
    - 请求完成之后,将request从列表中移除

    Flask源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from flask import Flask,session,request
     
    app = Flask(__name__)
     
    @app.route("/login",methods=["GET","POST"])
    def login():
        return "index"
     
    if __name__ == '__main__':
        #app.__call__()
        app.run()

    1. 执行app.__call__方法

    def __call__(self, environ, start_response):
            return self.wsgi_app(environ, start_response)

    2. 执行wsgi_app方法

    def wsgi_app(self, environ, start_response):
    
        ctx = self.request_context(environ)
        ctx.push()
    
        response = self.full_dispatch_request()

    2.1 生成RequestContext()对象 封装请求相关的数据(request,session)

    1
    ctx = self.request_context(environ)
    def request_context(self, environ):
        return RequestContext(self, environ)
    
    class RequestContext(object):
        def __init__(self, app, environ, request=None):
               self.app = app
               if request is None:
                request = app.request_class(environ)
               self.request = request

    2.2 将用户请求数据封装到Local()类中

    1
    ctx.push()
    def push(self):
    
        from .globals import _request_ctx_stack
    
        #将请求数据封装到Local()类
        _request_ctx_stack.push(self)
    
        #处理session
        self.session = self.app.open_session(self.request)
        if self.session is None:
            self.session = self.app.make_null_session()

    2.2.1 导入 _request_ctx_stack对象  内部会自动生成  { 线程或协程唯一标识:{"stack":[]} } 格式 

    1
    from .globals import _request_ctx_stack
    class Local(object):
    
        def __init__(self):
            object.__setattr__(self, '__storage__', {})
            object.__setattr__(self, '__ident_func__', get_ident)
    
        def __setattr__(self, name, value):
            ident = self.__ident_func__()
            storage = self.__storage__
            try:
                storage[ident][name] = value
            except KeyError:
                storage[ident] = {name: value}
    
    
    class LocalStack(object):
    
        def __init__(self):
            self._local = Local()
    
        def push(self, obj):
            rv = getattr(self._local, 'stack', None)
            if rv is None:
                self._local.stack = rv = []
            rv.append(obj)
            return rv
    
    _request_ctx_stack = LocalStack()

    2.2.2 执行_request_ctx_stack对象push方法  触发Local类的__setattr__方法 生成  { 线程或协程唯一标识:{"stack":[ RequestContext对象 ]} }

    1
    _request_ctx_stack.push(self)
    class Local(object):
    
        def __setattr__(self, name, value):
            ident = self.__ident_func__()
            storage = self.__storage__
            try:
                storage[ident][name] = value
            except KeyError:
                storage[ident] = {name: value}
    
    
    class LocalStack(object):
    
        def push(self, obj):
            """Pushes a new item to the stack"""
            rv = getattr(self._local, 'stack', None)
            if rv is None:
                self._local.stack = rv = []
    
            rv.append(obj)
            return rv
    
    _request_ctx_stack = LocalStack()

    2.2.3 self.session重新赋值

    1
    2
    3
    4
    RequestContext类的 self.session由none重新赋值为SecureCookieSessionInterface类open_session方法的结果(SecureCookieSession对象)
        - SecureCookieSession对象 就是一个字典
     
    self.session = self.app.open_session(self.request)
    def open_session(self, request):
        return self.session_interface.open_session(self, request)
     
    # 之后这里可以自定义自己类 可以继承SecureCookieSessionInterface类
    session_interface = SecureCookieSessionInterface()
    
    class SecureCookieSessionInterface(SessionInterface):
    
        def open_session(self, app, request):
            s = self.get_signing_serializer(app)
            if s is None:
                return None
    
            # 去cookie中获取session作为key 对应的值(包含了此用户的session数据) 
            val = request.cookies.get(app.session_cookie_name)
            if not val:
                return self.session_class()
            max_age = total_seconds(app.permanent_session_lifetime)
            try:
                data = s.loads(val, max_age=max_age)
                return self.session_class(data)
            except BadSignature:
                return self.session_class()

    3. 之后调用request

    #此时你如果调用request 会执行如下代码
    request = LocalProxy(partial(_lookup_req_object, 'request'))
        _lookup_req_object 获取RequestContext()中用户的请求数据

    4. 执行视图函数

    1
    response = self.full_dispatch_request()

    4.1 触发只执行一次的装饰器函数 @before_first_request 

    self.try_trigger_before_first_request_functions()

    4.2 # 触发Flask的信号  需要pip3 install blinker

    1
    request_started.send(self)

    4.3 执行特殊装饰器  @before_request

    有返回值 返回用户 
    没有返回值 触发并执行视图函数
    rv = self.preprocess_request()
    if rv is None:
        rv = self.dispatch_request()

    4.4 执行请求之后的装饰器  @after_request  且处理session

    return self.finalize_request(rv)
    
        def finalize_request(self, rv, from_error_handler=False):
    
            response = self.process_response(response)
    
                def process_response(self, response):
    
                    # 处理session
                    if not self.session_interface.is_null_session(ctx.session):
                    self.save_session(ctx.session, response)

     

     

     

      

      

      

      

      

  • 相关阅读:
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第4章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第3章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第1,2章 读书笔记(待更新)
    Tkinter的Message组件
    Git 实操/配置/实践
    mysq5.7.32-win安装步骤
    行为型模式之模板方法
    结构型模式之组合模式
    结构型模式之享元模式
    结构型模式之外观模式
  • 原文地址:https://www.cnblogs.com/zhangningyang/p/8259418.html
Copyright © 2011-2022 走看看