Flask上下文管理

前戏

# by gaoxin
from functools import partial


def add(x, y, z):
    print(x + y + z)

# 这是最简单的一个函数
# 如果我要实现一个功能,三个数相加,其中一个数必须是6
# 我们就可以使用偏函数来帮着我们传参

new_func = partial(add, 6)

new_func(1,1)
new_func(1,2)
new_func(1,3)
偏函数
# by gaoxin


class A(object):
    def __init__(self):
        # self.x1 = {}
        object.__setattr__(self, "x1", {})

    def __setattr__(self, key, value):
        print(key, value, self.x1)
        if key in self.x1:
            print(key, value)


a = A()
a.xx = 123
__setattr__

Flask上下文管理  一

Flask的上下文管理我们可以简单的理解为一个生命周期~

也就是请求进来到请求走一共做了哪些事情~~我们从源码开始走~~

首先我们知道项目启动执行了app.run()方法~~调用了werkzeug的run_simple()方法~

run_simple(host, port, self, **options) 这时候的self就是我们的app~

run_simple会执行self(),也就是app(), 那么app = Flask()  所以会走Flask的__call__方法~

那么__call__做了什么呢~~

environ是我们请求来的原始数据~当成参数传递给了request_context方法~~

进入这个RequestContext对象~

在这里重新封装了request, 以及给session 赋值了 None~~

这是初始化这个类做的一些事情~~也就说~

ctx = RequestContext(app, environ)  

ctx.request 是重新封装的request

ctx.session = None

然后我们继续往下走~~~

ctx.push() 那么这个RequestContext这个类里就一定有push方法~

我们是执行ctx.push()~~所以self应该就是我们这个ctx对象~~

执行了_request_ctx_stack.push(ctx)~也就是说~~_request_ctx_stack它把我们的ctx对象push到了一个地方~~

我们的ctx这个对象~里面有request以及session~~

self._local就是Local()对象~~

我们看这个初始化方法~跟我们上面回忆的知识点是不是很像~~

就是给我们这个Local类初始化了两个属性~~__storage__ = {}  __ident_func__ = get_ident

那我们继续看LocalStark中push方法做了什么~~

回头看我们的wsgi_app, 里的ctx.push()就走完了~接下来就走我们的视图了~~~

那到这里~我们可以通过什么样的方法在我们视图中拿到这个request对象呢~~

request在ctx对象里~能通过ctx.request得到,那我们怎么得到ctx呢~

ctx被LocalStack对象放入到Local中了~~

# by gaoxin
from flask import Flask
from flask import globals

app = Flask(__name__)


@app.route("/")
def index():
    ctx = globals._request_ctx_stack.top
    print(ctx.request.method)
    return "index"



if __name__ == '__main__':
    app.run()
视图中获得request

在这里我们的上下文管理的第一部分就走完了~~

Flask上下文管理 二

我们之前走到ctx.push(), 接下来那个方法就是去走我们的视图函数了~~

在我们的视图函数中上面那种拿request的方法太费劲了~我们需要简单一点的拿到request~~

那么我们导入的request跟我们上面拿到的request一定是一样的~~那导入的这个request做了什么呢~~

reqeust是LocalProxy这个类的实例化对象~参数是一个偏函数~~

那当我们调用request.method 等方法的时候走的是LocalProxy这个类的__getattr__方法~~

这里的_get_current_object()相当于我们偏函数的执行~~

到这~就跟我们上面的取值方式一样了~~也就是说通过LocalStack方法去Local中去ctx对象~~

然后通过getattr 找到ctx.request~~~

也就是说这个LocalProxy就是一个帮助我们取值的代理~让我们的取值变的更加简单~~~

这个代理通过偏函数来绑定参数~~

ctx中封装了request,以及session~只不过到这里我们的session依然是空的~~

session的实现原理

首先请求进来的时候在Local中存放了ctx对象~这个对象里的session是None~~

当我们走完这个_reqeust_cts_stack.push(ctx)后,我们看它走了什么~~

 

也就是说~请求进来把ctx放入Local中后~~从前端解密了cookie~然后把解密数据好的数据给了self.session~~

然后继续走~

我们可以看到~session的原理是~~

从cookie中获取数据~解密存入session~~请求走的时候~~ 把session中数据取出来,加密, 给响应设置cookie~~

那么我们平时在视图中设置删除session的值~原来跟request是一样的~通过代理去修改Local中的数据~~~

应用上下文管理

应用上下文和请求上下文的原理和源码是一样的~~~

也就是说~我们请求上下文和应用上下文~分别建立了两个Local对象~~

两个Local对象数据结构都是一样的~~那么请求上下文和应用上下文为什么要分开存放呢~~~

以后我们写离线脚本的时候大家就知道了~~~总之~~有用!!!!!

全局对象g

我们说应用上下文里封装了g对象~~那么这个g对象是什么呢~~~

Flask中g的生命周期?  

g和session有什么区别?

g和全局对象有什么区别~~

1--我们讲这么多上下文管理~~我们知道请求进来会为每个请求在Local中建立一个独立空间~~

    也就是在应用上下文的Local对象中建立了一个g对象~~当请求走的时候~~~就会删除~~

   所以g的生命周期是请求进来到走~~~

2--session不一样的是保存在cookie中~所以下次请求来的时候cookie带来了~~~

3--全局变量~~是在项目启动创建的~~

  无论多少请求进来都可以访问全局变量~~

我们的g对象一般情况用于before_request中设置值~只为这一次请求建立全局变量~~~

!!注意在我们重定向的时候还可以取g的值么~~~

 

posted @ 2018-12-29 02:20  GGG_XXX  阅读(401)  评论(0编辑  收藏  举报