应用情境

应用情境在请求、CLI命令或其他活动期间跟踪应用级数据。而不是将应用程序传递给每个函数,而是代之以访问 current_app 和 g 代理。

这与请求情境很类似,它在请求期间跟踪请求级数据,推送请求情境时会推送相应的应用情境。

情境的目的

这个 Flask 应用程序对象具有例如config之类的属性,这对于在视图和 CLI commands 的访问中很有用. 但是,在项目中的模块内导入 app实例中容易出现循环导入问题。当使用应用程序工厂方案或编写可重用的 blueprints或extensions 时,根本不会有应用程序要导入的实例。

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的常见用法是在请求期间管理资源。

  1. get_X() 创建资源 X ,如果它不存在,则将其缓存为 g.X .
  2. 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():
    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。