请求上下文管理流程:
- 请求到来之后wsgi会触发__call__方法,由__call__方法再次调用wsgi_app方法 - 在wsgi_app方法中: - 首先将 请求相关+空session 封装到一个RequestContext对象中,即:ctx。 - 将ctx交给LocalStack对象,再由LocalStack将ctx添加到Local中,Local结构: __storage__ = { 1231:{stack:[ctx,] } } - 根据请求中的cookie中 提取 名称为sessionid对应的值,对cookie进行加密+反序列化,再次赋值给ctx中的session -> 执行视图函数 - 把session中的数据再次写入到cookie中。 - 将ctx删除 - 结果返回给用户浏览器 - 断开socket连接
概要
# 1 请求到来时候: # ctx = RequestContext(self, environ) # self是app对象,environ请求相关的原始数据 # ctx.request = Request(environ) # ctx.session = None # 将包含了request/session的ctx对象放到“空调” { 1232:{ctx: ctx对象} 1231:{ctx: ctx对象} 1211:{ctx: ctx对象} 1111:{ctx: ctx对象} 1261:{ctx: ctx对象} } # 2 视图函数获取request/session: #视图函数在获取request / session时,内部隐含的操作是根据当前线程 / 协程的唯一标识取到ctx对象,再去ctx对象取request / session # 方式一:直接找LocalStack获取 from flask.globals import _request_ctx_stack.top print(_request_cxt_stack.top.request.method) # 方式二:通过代理LocalProxy获取 from flask import Flask,request print(request.method) # 3 请求结束: # 根据当前线程的唯一标记,将“空调”上的数据移除。
一 flask请求上下文管理流程图
三、请求上下文和app上下文:
- 请求上下文(ctx=RequestContext()):request/session - App上下文(app_ctx=AppContext()): app/g - 程序启动: 两个Local: local1 = { } local2 = { } 两个LocalStack: _request_ctx_stack _app_ctx_stack - 请求到来 对数据进行封装: ctx = RequestContext(request,session) app_ctx = AppContext(app,g) 保存数据: 将包含了(app,g)数据的app_ctx对象,利用 _app_ctx_stack(LocalStack())将app_ctx添加到Local中 storage = { 1231:{stack:[app_ctx(app,g),]} } 将包含了request,session数据的ctx对象,利用_request_ctx_stack(刘淞,LocalStack()),将ctx添加到Local中 storage = { 1231:{stack:[ctx(request,session),]} } - 视图函数处理: from flask import Flask,request,session,current_app,g app = Flask(__name__) @app.route('/index') def index(): # 去请求上下文中获取值 _request_ctx_stack request.method # 找小东北获取值 session['xxx'] # 找龙泰获取值 # 去app上下文中获取值:_app_ctx_stack print(current_app) print(g) return "Index" if __name__ == '__main__': app.run() app.wsgi_app - 结束 _app_ctx_stack.pop() _request_ctx_stack.pop()
问题:
1. Flask中g的生命周期? 当每次请求进来的时候,会为每个请求创建一个g,在请求结束的时候g被移出; 也就是说g只存在与当前请求的生命周期内 2. g和session一样吗? 不一样,g在请求结束的时候被清除了;session在请求结束的时候写入cookie中,请求来的时候可以从cookie中进行读取 3. g和全局变量一样吗? 不一样: 全局变量在项目启动的时候被创建,g在请求来的时候被创建 多线程,多线程来的时候操作全局变量会有问题,但g放在Local中,Local根据线程的唯一标识进行拆分开了 全局变量设置完后会存放在内存中,没有被销毁,下次来还能读,而g被删掉了 4.g的使用场景 一次http请求内,如果先做一次操作再后做一个操作,后一个操作需要前面给它设置一些值的时候可以用到g
二 flask-session
pip3 install flask-session
1、使用
import redis from flask import Flask,sessionfrom flask_session import Session app = Flask(__name__) app.config['SESSION_TYPE'] = 'redis' app.config['SESSION_REDIS'] = redis.Redis(host='140.143.227.206',port=6379,password='1234') Session(app) @app.route('/login') def login(): session['user'] = 'alex' return 'asdfasfd' @app.route('/home') def index(): print(session.get('user')) return '...' if __name__ == '__main__': app.run()
2、原理
- session数据保存到redis session:随机字符串1:q23asifaksdfkajsdfasdf session:随机字符串2:q23asifaksdfkajsdfasdf session:随机字符串3:q23asifaksdfkajsdfasdf session:随机字符串4:q23asifaksdfkajsdfasdf session:随机字符串5:q23asifaksdfkajsdfasdf - 随机字符串返回给用户。 随机字符串 源码: from flask_session import RedisSessionInterface