Django Middleware: An overview of middleware
The Django web framework contains hooks enabling a global mechanism for modifying the request and/or response in between the web-server interface and the view. Django middleware are the components that make use of these hooks.
An example of Django middleware is a component that adds a user
attribute to each incoming HttpRequest
.
This post provides an overview of middleware in the Django web framework.
Note: This post refers to the style of middleware introduced with Django 1.10. For syntax and details on middleware prior to version 1.10 refer to the Django documentation.
How middleware fits into the request/response cycle
Django middleware runs between Django receiving a request and processing the view, and again between view processing and serving the response from the web-server interface. The following diagram gives a high level view of middleware interaction with other components:
Diagram of example middleware in relation to other Django components
Enabling middleware
A middleware component is enabled by specifying the Python dotted path of the middleware's factory method or class in the MIDDLEWARE
setting. The MIDDLEWARE
setting generated by the django-admin startproject
command provides a good example of how middleware is specified.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Ordering middleware execution
The order in which middleware are defined in the MIDDLEWARE
setting determines the order that Django applies the middleware during the request/response phases:
- Middleware is applied in the order define by the
MIDDLEWARE
setting during the request phase. - During the response phase middleware is applied in the reverse order.
Some middleware depend on processing done in other middleware so it is important to order middleware correctly. The MIDDLEWARE
setting generated by django-admin startproject
shows the proper ordering for the default middleware. If you intend to include other middleware please review the Django docs for information on dependencies between the various middleware classes.
Short-circuiting execution
The basic model on which all middleware operates expects each middleware to call the get_response
callable in order to pass execution to the next middleware or to the view middleware if there are no further middleware in the chain.
A middleware implemented using a class will have the following basic structure:
class SampleMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed in the request processing phase
# Let the get_response callable pass processing to
# the next middleware
response = self.get_response(request)
# Code to be executed in the response processing phase
return response
Returning a response without calling get_response
short-circuits middleware execution. In this case, later middleware is not called for processing of either the request or response phase. View processing also does not occur. The same middleware (in reverse order) that the request was processed through is given an opportunity to process the response.
Further details
A few other hooks are available for class-based middleware that allow some deviation from the basic pattern described here. Refer to the Django documentation for further details on additional middleware hooks: process_view(), process_exception() and processtemplateresponse().