什么时候应该使用Flask.g?
我看到 g
将从请求上下文移动到Flask 0.10中的应用上下文,这使我对g
的预期用法感到困惑。
我的理解(对于Flask 0.9)是这样的:
-
g
位于请求上下文中,即在请求开始时重新创build,并且可用直到结束 -
g
旨在用作“请求黑板”,我可以在请求期间放置相关内容(即,在请求开始时设置一个标志,并在最后处理它,可能来自before_request
/after_request
对) -
g
可以并且应该用于资源pipe理,即保存数据库连接等。
在Flask 0.10中哪些句子不再是真的? 有人可以指点我一个资源,讨论改变的原因吗? 我应该在Flask 0.10中使用什么作为“请求黑板” – 我是否应该创build自己的应用程序/扩展特定的线程本地代理并将其推送到上下文堆栈before_request
? 在应用程序上下文中,资源pipe理的重点是什么?如果我的应用程序长期存在(不像请求),那么资源永远不会被释放?
由Markus链接的高级烧瓶模式解释了0.10中g
一些变化:
-
g
现在生活在应用程序上下文中。 - 每个请求都会推送一个新的应用程序上下文 ,擦除旧的应用程序上下文 ,所以仍然可以使用
g
来设置每个请求标志而不更改代码。 - 在调用
teardown_request
之后 ,应用程序上下文会popup。 (Armin的演示解释这是因为创build数据库连接的事情是为请求设置环境的任务,不应在before_request
和after_request
内处理)
作为这个主题中的信息的补充:我也对flask.g
的行为感到困惑,但是一些快速testing帮助我澄清了它。 这是我试过的:
from flask import Flask, g app = Flask(__name__) with app.app_context(): print('in app context, before first request context') print('setting g.foo to abc') g.foo = 'abc' print('g.foo should be abc, is: {0}'.format(g.foo)) with app.test_request_context(): print('in first request context') print('g.foo should be abc, is: {0}'.format(g.foo)) print('setting g.foo to xyz') g.foo = 'xyz' print('g.foo should be xyz, is: {0}'.format(g.foo)) print('in app context, after first request context') print('g.foo should be abc, is: {0}'.format(g.foo)) with app.test_request_context(): print('in second request context') print('g.foo should be abc, is: {0}'.format(g.foo)) print('setting g.foo to pqr') g.foo = 'pqr' print('g.foo should be pqr, is: {0}'.format(g.foo)) print('in app context, after second request context') print('g.foo should be abc, is: {0}'.format(g.foo))
以下是它的输出:
in app context, before first request context setting g.foo to abc g.foo should be abc, is: abc in first request context g.foo should be abc, is: abc setting g.foo to xyz g.foo should be xyz, is: xyz in app context, after first request context g.foo should be abc, is: xyz in second request context g.foo should be abc, is: xyz setting g.foo to pqr g.foo should be pqr, is: pqr in app context, after second request context g.foo should be abc, is: pqr
正如Y4Kman上面所说的,“每个请求推送一个新的应用程序上下文”。 正如Flask文档所说 ,应用程序上下文“不会在请求之间共享”。 现在,还没有明确的说明(尽pipe我猜这些陈述是隐含的),而且我的testing清楚地表明,你不应该明确地创build嵌套在一个应用程序上下文中的多个请求上下文,因为flask.g
(和co )没有任何魔法,它在上下文的两个不同的“层次”中起作用,不同的状态在应用程序和请求级别独立存在。
实际情况是,“应用程序上下文”可能是一个令人误解的名称,因为app.app_context()
是一个每个请求的上下文,与“请求上下文”完全一样。 把它看作是一个“request context lite”,只有在你需要某些通常需要请求上下文的variables的情况下才需要,但是你不需要访问任何请求对象(例如,当在一个shell脚本)。 如果您尝试扩展应用程序上下文以包含多个请求上下文,那么您就会遇到麻烦。 所以,而不是我上面的testing,而应该用Flask的上下文编写这样的代码:
from flask import Flask, g app = Flask(__name__) with app.app_context(): print('in app context, before first request context') print('setting g.foo to abc') g.foo = 'abc' print('g.foo should be abc, is: {0}'.format(g.foo)) with app.test_request_context(): print('in first request context') print('g.foo should be None, is: {0}'.format(g.get('foo'))) print('setting g.foo to xyz') g.foo = 'xyz' print('g.foo should be xyz, is: {0}'.format(g.foo)) with app.test_request_context(): print('in second request context') print('g.foo should be None, is: {0}'.format(g.get('foo'))) print('setting g.foo to pqr') g.foo = 'pqr' print('g.foo should be pqr, is: {0}'.format(g.foo))
哪个会给出预期的结果。