根据前一篇应用上下文可知,请求上下文的作用域是发生在请求到来之后。
如有一个应用函数返回用户应该跳转到的URL。想象它总是会跳转到URL的next参数,或HTTP referrer或索引页:
from flask import request,url_for
def redirect_url():
return request.args.get('next') or request.referrer or url_for('index')
如你所见,它访问了请求对象。当你试图在纯python shell中运行这段代码时,你会看见这样的异常:
Traceback (most recent call last):
File "<stdin>", line 1, in <module> File "<stdin>", line 2, in redirect_url File "/home/wang/myproject/venv/local/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__ return getattr(self._get_current_object(), name) File "/home/wang/myproject/venv/local/lib/python2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object return self.__local() File "/home/wang/myproject/venv/local/lib/python2.7/site-packages/flask/globals.py", line 20, in _lookup_req_object raise RuntimeError('working outside of request context')RuntimeError: working outside of request context这有很大意义,因为我们当前并没有可以访问的请求。所以我们需要制造一个请求并且绑定到当前的上下文。我们可以使用test_request_context()和request_context()创建RequestContext实例。其中,class flask.ctx.RequestContext(app,environ,request=None)
这 个类包含与请求相关的所有信息。该实例创建于请求的开始,然后将其压入_request_ctx_stack中,并且在结束时从栈中删除它。它将为 WSGI环境创建URL适配器和请求对象。然后,不能直接使用该类,而是用test_request_context()和 request_context()来创建。
request_context(environ) (environ是WSGI环境)和test_request_context(*args,**kwargs)用法一样,可以使用with或push()和pop()
使用push()和pop()方法:
>>>app=Flask(__name__)
>>>ctx=app.test_request_context('/?next=http://example.com/')
>>>ctx.push()
从这点开始,你可以使用请求对象:
>>>redirect_url()
u'http://example.com/'
直到你调用pop:
>>>ctx.pop()当使用with时:
>>>app=Flask(__name__)>>>with app.test_request_context('/?next=http://example.com/')
因为请求上下文在内部作为一个栈来维护,所以你可以多次压栈出栈。这在实现内部重定向之类的东西时很方便。
对于request_context()一样。
请求上下文内部工作如同一个栈。栈顶是当前活动的请求。push()把上下文添加到栈顶。pop()把它移出。在出栈时,应用teardown_request()函数也会被执行。
回调和错误:
在每个请求之前,执行 上绑定的函数。 如果这些函数中的某个返回了一个响应,其它的函数将不再被调用。任何情况下,无论如何这个返回值都会替换视图的返回值。
如果 上绑定的函数没有返回一个响应, 常规的请求处理将会生效,匹配的视图函数有机会返回一个响应。
视图的返回值之后会被转换成一个实际的响应对象,并交给 上绑定的函数适当地替换或修改它。
在请求的最后,会执行 上绑定的函数。这总会发生,即使在一个未处理的异常抛出后或是没有请求前处理器执行过 (例如在测试环境中你有时会想不执行请求前回调)
销毁和回调:
销毁回调是是特殊的回调,因为它们在不同的点上执行。严格地说,它们不依赖实际的请求处理,因为它们限定在 对象的生命周期。 当请求上下文出栈时, teardown_request() 上绑定的函数会被调用。
留意代理
Flask 中提供的一些对象是其它对象的代理。背后的原因是,这些代理在线程间共享, 并且它们在必要的情景中被调度到限定在一个线程中的实际的对象。
大多数时间你不需要关心它,但是在一些例外情况中,知道一个对象实际上是代理是有益的:
代理对象不会伪造它们继承的类型,所以如果你想运行真正的实例检查,你需要在被代理的实例上这么做(见下面的 _get_current_object )。
如果对象引用是重要的(例如发送 )
如果你需要访问潜在的被代理的对象,你可以使用 方法:
app = current_app._get_current_object() my_signal.send(app)
错误时的上下文保护
无论错误出现与否,在请求的最后,请求上下文会出栈,并且相关的所有数据会被销毁。在开发中,当你想在异常发生时,长期地获取周围的信息,这会成为麻烦。 在 Flask 0.6 和更早版本中的调试模式,如果发生异常,请求上下文不会被弹出栈, 这样交互式调试器才能提供给你重要信息。
从 Flask 0.7 开始,我们设定 PRESERVE_CONTEXT_ON_EXCEPTION 配置变量来更好地控制该行为。这个值默认与 DEBUG 的设置相关。当应用工作在调试模式下时,上下文会被保护,而生产模式下相反。
不要在生产模式强制激活 PRESERVE_CONTEXT_ON_EXCEPTION ,因为它会导致在异常时应用的内存泄露。不过,它在开发时获取开发模式下相同的错误行为来试图调试一个只有生产设置下才发生的错误时很有用。
在shell中使用上下文可参考:http://docs.jinkan.org/docs/flask/shell.html#shell
请求上下文: