Flask上下文管理
1,引入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
2,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中了~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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()
在这里我们的上下文管理的第一部分就走完了~
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的值么~