Flask Application Context¶
An active Flask application context is required to make queries and to access
db.engine
and db.session
. This is because the session is scoped to the context
so that it is cleaned up properly after every request or CLI command.
Regardless of how an application is initialized with the extension, it is not stored for
later use. Instead, the extension uses Flask’s current_app
proxy to get the active
application, which requires an active application context.
Automatic Context¶
When Flask is handling a request or a CLI command, an application context will automatically be pushed. Therefore you don’t need to do anything special to use the database during requests or CLI commands.
Manual Context¶
If you try to use the database when an application context is not active, you will see the following error.
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.
If you find yourself in a situation where you need the database and don’t have a
context, you can push one with app_context
. This is common when calling
db.create_all
to create the tables, for example.
def create_app():
app = Flask(__name__)
app.config.from_object("project.config")
import project.models
with app.app_context():
db.create_all()
return app
Tests¶
If you test your application using the Flask test client to make requests to your endpoints, the context will be available as part of the request. If you need to test something about your database or models directly, rather than going through a request, you need to push a context manually.
Only push a context exactly where and for how long it’s needed for each test. Do not push an application context globally for every test, as that can interfere with how the session is cleaned up.
def test_user_model(app):
user = User()
with app.app_context():
db.session.add(user)
db.session.commit()
If you find yourself writing many tests like that, you can use a pytest fixture to push a context for a specific test.
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()