flask上下文
flask项目中有两个上下文,一个是应用上下文(app),另外一个是请求上下文(request)。请求上下文request和应用上下文current_app都是一个全局变量。
flask有特殊的机制可以保证每次请求的数据都是隔离的,即A请求所产生的数据不会影响到B请求。所以可以直接导入request对象,也不会被一些脏数据影响了,并且不需要在每个函数中使用request的时候传入request对象。这两个上下文具体的实现方式和原理可以没必要详细了解。
- request:请求上下文上的对象。这个对象一般用来保存一些请求的变量。比如method、args、form等。
- session:请求上下文上的对象。这个对象一般用来保存一些会话信息。
- current_app:返回当前的app
- g:应用上下文的对象。处理请求时用作临时存储的对象。
current_app
- 倒入库
1 | from flask import Flask,session,current_app |
- 我们打印一下看看输出什么
1 2 3 4 5 6 | @app.route('/') def index(): username = session.get('username') print(username) print(current_app.name) return '这是首页' |
- 这并不是文件的名字,他是个对象,是flaks的app的名字
- 如果我们不在视图函数中用,直接写在外面呢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from flask import Flask,session,current_app import os from datetime import timedelta app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(12) app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=24) print(app) app2 = current_app print(app2) @app.route('/') def index(): username = session.get('username') print(username) print(current_app.name) return '这是首页' |
- 运行代码结果如下:
- 为什么会出错,因为在flask内部维护有两个栈,线程隔离的栈,current_app指的是应用上下文
- 他们都在栈顶。他们应用的时候都会被压入栈里面,接下来他会判断应用上下(app)文是否为空,若为空他会向栈中压入app这个对象
- 反正就理解为current_app在外面用不了
- 如果要在外面用,可以采用使用一个上下文的机制,用一个with语句
1 2 3 4 | print(app) with app.app_context(): app2 = current_app print(app2) |
这样就能在外面获取到current_app了
g:
- 倒入库
1 | from flask import Flask,session,current_app,g |
- 创建一个工具包
- 为什么创建工具包,我我一般把一些工具写入一个新的文件中,如果我们有用到的地方直接导入他就可以了 ,写一次,可用多次,舒服!
- 我们先不用g对象
1 2 3 4 5 6 | utils.py文件 def log_a(username): print('log a %s'%username) def log_b(username): print('log b %s'%username) |
- 我们要调用这两个函数就要先导入他
1 | from utils import log_a,log_b |
- 然后我们打印一下
1 2 3 4 5 6 | @app.route('/') def index(): username = session.get('username') log_a(username) log_b(username) return '这是首页' |
- 初始代码,接着上一张的,方便观看我在发一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | from flask import Flask,session,current_app,g import os from datetime import timedelta from utils import log_a,log_b app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(12) app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=24) print(app) with app.app_context(): app2 = current_app print(app2) @app.route('/') def index(): username = session.get('username') log_a(username) log_b(username) return '这是首页' @app.route('/login/') def login(): # 字典 session['username'] = 'zaaaacki' # 过期时间设置 session.permanent = True return '登陆页面' @app.route('/logout/') def logout(): # 删除session session.pop('username') # 清空session session.clear() return '这是退出页面' if __name__ == '__main__': app.run(debug=True) |
- 打开网址,因为我们的username在login路由中,所以我们先打开login路由再进入首页
返回成功
- 我们用g对象的方法
- 首先在工具文件utils中导入库
1 | from flask import g |
- 然后在utils文件中使用我们的g对象
1 2 3 4 5 | def log_a(): print('log a %s'%g.username) def log_b(): print('log b %s'%g.username) |
- 因为我们的g就是保存临时信息内容的,所以前面这部分的username就应该去掉
- 然后通过g.username = username 来获取username
1 2 3 4 5 6 7 | @app.route('/') def index(): username = session.get('username') g.username = username log_a() log_b() return '这是首页' |
- 记住我们g对象只能保存一次,我们访问一次他拿一次
- 做个演示:
- 首先我们的代码是这样的,我们打开首页,然后打开login页面,获取username然后返回首页,返回
- 然后我们在写一个hello函数
- 刷新一下,返回了这个,因为我们的g对象只能保存一次