Flask 应用程序上下文

需要一个活动 Flask 应用程序上下文来进行查询并访问 db.enginedb.session。这是因为会话的范围限定在上下文中,以便在每个请求或 CLI 命令后正确清理会话。

无论如何使用扩展初始化应用程序,都不会将其存储以备后用。相反,扩展使用 Flask 的 current_app 代理来获取活动应用程序,而这需要一个活动应用程序上下文。

自动上下文

当 Flask 处理请求或 CLI 命令时,将自动推送应用程序上下文。因此,您无需执行任何特殊操作即可在请求或 CLI 命令期间使用数据库。

手动上下文

如果您尝试在应用程序上下文不活动时使用数据库,您将看到以下错误。

RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.

如果您发现自己处于需要数据库但没有上下文的境况,您可以使用 app_context 推送一个上下文。例如,在调用 db.create_all 以创建表时,这很常见。

def create_app():
    app = Flask(__name__)
    app.config.from_object("project.config")

    import project.models

    with app.app_context():
        db.create_all()

    return app

测试

如果您使用 Flask 测试客户端测试您的应用程序以向您的端点发出请求,则上下文将作为请求的一部分可用。如果您需要直接测试有关您的数据库或模型的内容,而不是通过请求,则需要手动推送一个上下文。

仅在每个测试确实需要时,在需要的时间范围内推送上下文。不要为每个测试全局推送应用程序上下文,因为这会干扰会话的清理方式。

def test_user_model(app):
    user = User()

    with app.app_context():
        db.session.add(user)
        db.session.commit()

如果您发现自己编写了许多这样的测试,您可以使用 pytest 夹具为特定测试推送上下文。

import pytest

@pytest.fixture
def app_ctx(app):
    with app.app_context():
        yield

@pytest.mark.usefixtures("app_ctx")
def test_user_model():
    user = User()
    db.session.add(user)
    db.session.commit()