Skip to main content

Application Fundamentals

The Flask application object is the central registry for your application's configuration, routes, and error handlers. It implements the WSGI interface, allowing it to be served by any standard web server like Gunicorn or uWSGI.

The Flask Application Object

At its core, a Flask application is an instance of the Flask class. This class inherits from App (in src/flask/sansio/app.py) and Scaffold (in src/flask/sansio/scaffold.py), which provide the infrastructure for registering view functions, managing static files, and handling templates.

When you instantiate Flask, you must provide an import_name. This is typically __name__ if you are using a single module, or the name of your package. Flask uses this name to locate resources like templates and static files on the filesystem.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
return "Hello, World!"

The Application Factory Pattern

In larger applications, instead of creating a global Flask instance, you should use the application factory pattern. This involves defining a function that creates and configures the app instance. This pattern is essential for testing, as it allows you to create multiple instances of the app with different configurations.

The following example from examples/tutorial/flaskr/__init__.py demonstrates this pattern:

import os
from flask import Flask

def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY="dev",
DATABASE=os.path.join(app.instance_path, "flaskr.sqlite"),
)

if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile("config.py", silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)

# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass

# a simple page that says hello
@app.route("/hello")
def hello():
return "Hello, World!"

from . import db
db.init_app(app)

from . import auth
app.register_blueprint(auth.bp)

return app

The WSGI Application Lifecycle

When a WSGI server receives a request, it calls the Flask application object. This entry point is implemented in the wsgi_app method in src/flask/app.py. The lifecycle follows a strict sequence of pushing a context, dispatching the request, and popping the context.

def wsgi_app(self, environ, start_response):
# 1. Create a combined application and request context
ctx = self.request_context(environ)
error = None
try:
try:
# 2. Push the context to the stack
ctx.push()
# 3. Dispatch the request and get a response
response = self.full_dispatch_request(ctx)
except Exception as e:
error = e
# 4. Handle exceptions if they occur during dispatch
response = self.handle_exception(ctx, e)
# 5. Return the WSGI response
return response(environ, start_response)
finally:
# 6. Pop the context, triggering teardown handlers
ctx.pop(error)

Request Dispatching and Processing

The full_dispatch_request method manages the high-level flow of a single request. It handles pre-processing, the actual view execution, and post-processing.

  1. Pre-processing: Flask calls preprocess_request, which executes any functions decorated with @app.before_request. If any of these functions return a value, Flask stops further processing and treats that value as the response.
  2. Dispatching: If no pre-processor returned a value, dispatch_request is called. It matches the request URL against the routing table and executes the associated view function.
  3. Finalizing: The return value from the view (or a pre-processor) is passed to finalize_request. This method converts the return value into a proper Response object (via make_response) and then runs post-processing functions decorated with @app.after_request.

Context Management

Flask uses a context-based system to make data like the current request or application configuration available globally without passing them to every function.

The AppContext

As of Flask 3.2, the AppContext (defined in src/flask/ctx.py) is a combined context that manages both application-level and request-level data. When a request starts, an AppContext is created and pushed.

The context manages several key pieces of data:

  • app: The current Flask application instance.
  • request: The Request object for the current HTTP request.
  • session: The session object, which is loaded from the request on first access.
  • g: A general-purpose namespace for storing data during a request (an instance of _AppCtxGlobals).

Context Proxies

To access these objects, Flask provides "proxies" in flask.globals. These proxies always point to the object associated with the currently active context.

  • current_app: Points to the Flask instance.
  • request: Points to the current Request.
  • session: Points to the current Session.
  • g: Points to the current g object.

If you try to access these proxies outside of a context (e.g., in a background thread or a script), Flask raises a RuntimeError. You can manually push a context using the app_context() context manager:

with app.app_context():
print(current_app.name)
# Perform operations that require an active application context

Teardown and Cleanup

When the context is popped at the end of a request, Flask executes teardown handlers registered with @app.teardown_request and @app.teardown_appcontext. These are called even if an unhandled exception occurred, making them ideal for closing database connections or releasing resources.

Note that in Flask 3.2, error handling methods like handle_http_exception and handle_user_exception now require the AppContext as their first argument:

def handle_exception(self, ctx: AppContext, e: Exception) -> Response:
# ... implementation ...