Over my web development journey I started using and falling in love with Flask for website development and web app development. Even thought I was familiar with flask, its most used extensions, something that eluded or confused every now and then was the flask application context. None of the online explanations were clear or satisfactory for a beginner who was not exposed to flask internals. These two examples cemented my understanding of the application context.
Here it goes..In Flask, a context is an internal mechanism that allows certain variables to become globally accessible, while still being local to a particular thread. There are two types of contexts in Flask: the application context and the request context.
The application context is associated with the Flask application instance, and it’s used for things like database connections, configurations, and other application-level variables. The request context is tied to the HTTP request and includes things like request data, session data, and the current user.
app.app_context()
is a method that returns an application context for the Flask application instance app
.
You can use the with
statement to push an application context onto the context stack, which makes it the current context. Within this block, you can use current_app
and g
(which are both application context globals) as if they were global variables, but they’re actually thread-local and specific to the current context.
For instance:
with app.app_context():
# within this block, current_app points to app and
# g is available
print(current_app.name)
g.foo = 'bar'
The context is automatically popped off the stack when the with
block ends, and current_app
and g
are no longer available.
In the context of db.create_all()
, you need an application context because db.create_all()
needs to know which application it’s creating tables for. Normally, Flask automatically pushes an application context for you when handling a request, but if you’re running code outside of a request (like in a setup script or a shell), you need to manually push an application context with with app.app_context():
.
Makes sense? Not to me it didn’t. I got an inkling of how it works but still couldn’t visualise until there were concrete examples that a non-coder could understand.
Let’s break it down with the two examples I promised.
Example 1.
Imagine you’re running a city (your application). This city has lots of services – water, electricity, internet, garbage collection, etc. Each house (or thread) in the city uses these services independently. For example, when you turn on the tap in your house, you don’t want water flowing in someone else’s house!
Flask’s “context” is like the connection between each house and the city’s services. When a house needs water, it uses its “water context” to get water from the city’s water service. This “water context” makes sure that the water goes to the right house and that the houses don’t interfere with each other.
The app.app_context()
in Flask is similar. It’s like a contract that connects your current task (say, a user’s request, or setting up the database) with the application’s services (like the database connection, configuration settings, etc.). This allows each task to use these services independently, without interfering with other tasks.
Here’s an example: When you run db.create_all()
, Flask needs to know which application’s database to set up. It gets this information from the application context. If you’re handling a user’s request, Flask automatically creates this context for you. But if you’re setting up the database before any user requests have come in, you need to create the application context yourself using with app.app_context():
.
Hope this provides clarity. Here’s the second example to cement the concept.
Example 2.
Let’s use a real-life scenario to understand this concept.
Consider an international company with several departments like Accounting, Marketing, and Human Resources. Each department has its own set of rules, systems, and resources. When an employee is working within a department, they use the resources and follow the rules specific to that department.
Think of each department as an “application context”. When an employee enters a department (let’s say, Accounting), they are effectively entering the “Accounting context”. While in this context, they have access to accounting resources (like the company’s financial records), and they have to follow accounting rules (like confidentiality regulations).
Just like an employee can’t access the accounting systems from the marketing department, in Flask, certain pieces of data and functionality can’t be accessed outside of an application context. This includes things like the database connection, the current user, or the configuration for the current application.
When a request comes into a Flask application, Flask automatically creates an application context, which gets torn down when the request finishes. But if you need to access these resources outside of a request (like in a command-line command, a background thread, or during testing), you have to manually create an application context using app.app_context()
.
When you create an application context with app.app_context()
, it’s like you’re stepping into a department at the company. You can now access the resources and follow the rules specific to that context. When you’re done, you leave the context, and the resources are no longer accessible. Here’s an example of how you would do this in code:
with app.app_context():
# Now we're in the application context
# We can do things like interacting with the database
user = User.query.get(1)
# We're outside of the application context now
# We can still use the 'user' object we got while in the context, but we can't do another query
This concept of contexts can be confusing if you’re new to Flask, but it’s a powerful tool that allows Flask to keep data separate for different requests, even when handling multiple requests at the same time.
I keep coming back to these two examples whenever I need a refresher.