应用上下文¶
应用上下文在请求、CLI 命令或其他活动期间跟踪应用程序级别的数据。无需将应用程序传递给每个函数,而是访问 current_app
和 g
代理。
这类似于请求上下文,后者在请求期间跟踪请求级别的数据。当请求上下文被推送时,也会推送相应的应用上下文。
上下文的目的¶
Flask
应用程序对象具有诸如 config
之类的属性,这些属性在视图和 CLI 命令 中访问非常有用。但是,在项目模块中导入 app
实例很容易出现循环导入问题。当使用 应用工厂模式 或编写可重用的 蓝图 或 扩展 时,根本不会有 app
实例可供导入。
Flask 通过应用上下文解决此问题。与其直接引用 app
,不如使用 current_app
代理,它指向处理当前活动的应用程序。
当处理请求时,Flask 会自动推送应用上下文。在请求期间运行的视图函数、错误处理程序和其他函数将可以访问 current_app
。
当运行使用 @app.cli.command()
注册到 Flask.cli
的 CLI 命令时,Flask 也会自动推送应用上下文。
上下文的生命周期¶
应用上下文是根据需要创建和销毁的。当 Flask 应用程序开始处理请求时,它会推送一个应用上下文和一个 请求上下文。当请求结束时,它会弹出请求上下文,然后弹出应用上下文。通常,应用上下文的生命周期与请求相同。
有关上下文如何工作以及请求的完整生命周期的更多信息,请参阅请求上下文。
手动推送上下文¶
如果您尝试在应用上下文之外访问 current_app
或任何使用它的内容,您将收到此错误消息
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that
needed to interface with the current application object in some way.
To solve this, set up an application context with app.app_context().
如果您在配置应用程序时(例如在初始化扩展时)看到该错误,则可以手动推送上下文,因为您可以直接访问 app
。在 with
代码块中使用 app_context()
,并且在该代码块中运行的所有内容都将可以访问 current_app
。
def create_app():
app = Flask(__name__)
with app.app_context():
init_db()
return app
如果您在代码中的其他地方看到该错误,而不是与配置应用程序相关,则很可能表明您应该将该代码移动到视图函数或 CLI 命令中。
存储数据¶
应用上下文是在请求或 CLI 命令期间存储常用数据的好地方。Flask 提供了 g 对象
用于此目的。它是一个简单的命名空间对象,与应用上下文具有相同的生命周期。
注意
g
名称代表 “global”(全局),但这指的是数据在上下文内是全局的。g
上的数据在上下文结束后会丢失,并且它不适合存储跨请求的数据。使用 session
或数据库来存储跨请求的数据。
g
的常见用途是在请求期间管理资源。
get_X()
创建资源X
(如果它不存在),并将其缓存为g.X
。teardown_X()
关闭或以其他方式释放资源(如果存在)。它被注册为teardown_appcontext()
处理程序。
例如,您可以使用此模式管理数据库连接
from flask import g
def get_db():
if 'db' not in g:
g.db = connect_to_database()
return g.db
@app.teardown_appcontext
def teardown_db(exception):
db = g.pop('db', None)
if db is not None:
db.close()
在请求期间,每次调用 get_db()
都将返回相同的连接,并且它将在请求结束时自动关闭。
您可以使用 LocalProxy
从 get_db()
创建新的上下文本地代理
from werkzeug.local import LocalProxy
db = LocalProxy(get_db)
访问 db
将在内部调用 get_db
,方式与 current_app
的工作方式相同。
事件和信号¶
当应用上下文弹出时,应用程序将调用使用 teardown_appcontext()
注册的函数。
发送以下信号:appcontext_pushed
、 appcontext_tearing_down
和 appcontext_popped
。