目录
Flask提供了两种上下文环境,一个是应用上下文(Application Context),另一个是请求上下文(Request Context)。从名字上就可以知道一个是应用级别的,另一个是单个请求级别的。
- request:请求上下文上的对象。这个对象一般用来保存一些请求的变量。比如
method
、args
、form
等。 - session:请求上下文上的对象。这个对象一般用来保存一些会话信息。
- current_app:返回当前的app。
- g:应用上下文上的对象。处理请求时用作临时存储的对象。
1、应用上下文环境
Flask 背后的设计理念之一就是,代码在执行时会处于两种不同的“状态”(states)。 当 Flask 对象被实例化后在模块层次上应用便开始隐式地处于应用配置状态。一直到第一个请求还是到达这种状态才隐式地结束。当应用处于这个状态的时候 ,你可以认为下面的假设是成立的:
- 程序员可以安全地修改应用对象
- 目前还没有处理任何请求
- 你必须得有一个指向应用对象的引用来修改它。不会有某个神奇的代理变量指向你刚创建的或者正在修改的应用对象的
相反,到了第二个状态,在处理请求时,有一些其它的规则:
- 当一个请求激活时,上下文的本地对象( flask.request 和其它对象等) 指向当前的请求
- 你可以在任何时间里使用任何代码与这些对象通信
current_app 上下文本地变量就是应用上下文驱动的。
1.1、应用上下文的作用
Flask 设计的支柱之一是你可以在一个 Python 进程中拥有多个应用。
那么代码如何找到“正确的”应用?在过去,我们推荐显式地到处传递应用,但是这会让我们在使用不是以这种理念设计的库时遇到问题。
解决上述问题的常用方法是使用后面将会提到的 current_app 代理对象,它被绑定到当前请求的应用的引用。既然无论如何在没有请求时创建一个这样的请求上下文是一个没有必要的昂贵操作,应用上下文就被引入了。
current_app代理
介绍完请求级别的上下文环境,我们再来了解应用级别的上下文环境。先来看一段代码:
from flask import Flask, current_app
app = Flask('SampleApp')
@app.route('/')
def index():
return 'Hello, %s!' % current_app.name
我们可以通过”current_app.name”来获取当前应用的名称,也就是”SampleApp”。”current_app”是一个本地代理,它的类型是”werkzeug.local. LocalProxy”,它所代理的即是我们的app对象,也就是说”current_app == LocalProxy(app)”。使用”current_app”是因为它也是一个ThreadLocal变量,对它的改动不会影响到其他线程。你可以通过”current_app._get_current_object()”方法来获取app对象。
既然是ThreadLocal对象,那它就只在请求线程内存在,它的生命周期就是在应用上下文里。离开了应用上下文,”current_app”一样无法使用。
app = Flask('SampleApp')
print current_app.name
RuntimeError: working outside of application context
1.2、构建应用上下文环境
有两种方式来创建应用上下文。第一种是隐式的:无论何时当一个请求上下文被压栈时, 如果有必要的话一个应用上下文会被一起创建。由于这个原因,你可以忽略应用上下文的存在,除非你需要它。
第二种是显式地调用 app_context() 方法:
from flask import Flask, current_app
app = Flask(__name__)
with app.app_context():
# within this block, current_app points to app.
print current_app.name
“app_context()”方法会创建一个”AppContext”类型对象,即应用上下文对象,此后我们就可以在应用上下文中,访问”current_app”对象了。
1.3、应用上下文的实现方式
应用上下文会在必要时被创建和销毁。它不会在线程间移动,并且也不会在不同的请求之间共享。正因为如此,它是一个存储数据库连接信息或是别的东西的最佳位置。内部的栈对象叫做