应用程序上下文 — Flask 文档
应用程序上下文
应用程序上下文在请求、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 的一个常见用途是在请求期间管理资源。
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 的工作方式相同。
如果您正在编写扩展,则 g 应保留用于用户代码。 您可以在上下文本身上存储内部数据,但一定要使用足够独特的名称。 当前上下文通过 _app_ctx_stack.top 访问。 有关更多信息,请参阅 Flask 扩展开发 。
事件和信号
当应用程序上下文被弹出时,应用程序将调用用 teardown_appcontext()
注册的函数。
如果 signals_available 为真,则发送以下信号:appcontext_pushed、appcontext_tearing_down 和 appcontext_popped。