python全栈034—–flask上下文,current_app,g

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对象只能保存一次