As mentioned in the Django official docs, Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.
Each middleware component is responsible for doing some specific function. For example, Django includes a middleware component called AuthenticationMiddleware, that associates users with requests using sessions.
The following example creates a custom middleware to log reponses which take more that 2 seconds to complete.
- Create a python package (a folder with __init__.py inside) named as middleware
- Create a file named, for instance, slow_api_log.py and a regular Python class in it like bellow:
To enable the custom middleware, just add the path to the file in the MIDDLEWARE list in settings.py.
MIDDLEWARE = [
# ENABLE THE NEW MIDDLEWARE
The two required methods in all Django middleware class :
__init__.- Used in all Python classes to bootstrap object instances. The
__init__method in Django middleware classes only gets called once, when the web server backing the Django application starts. The
__init__method in Django middleware must declare a
get_responseinput, which represents a reference to a prior middleware class response. The
get_responseinput is assigned to an instance variable -- also named
get_response-- which is later used in the main processing logic of the middleware class.
__call__.- Used in all Python classes to call an object instance as a function. The
__call__method in Django middleware classes is called on every application request. The
__call__method declares a
requestinput which represents the same
HttpRequestobject used by view methods. The
__call__method goes through three phases:
- Before view method call.- Once the
__call__method is triggered, you get the opportunity to alter the
requestreference before it's passed to a view method. If you want to add or modify something in
requestbefore it gets turned over to a view method, this is the phase to do it in.
- Trigger view method call.- After you modify (or not) the original
request, you must turn over control to the view method in order for it to run. This phase is triggered when you pass
self.get_responsereference you set in the
__init__method. This phase effectively says "I'm done modifying the
request, go ahead and turn it over to the view method so it can run".
- Post view method call.- Once a view method finishes, the results are assigned to the
__call__. In this phase, you have the opportunity to perform logic after a view method finishes. You exit this phase by simply returning the
responsereference from the view method (i.e.
In summary, the execution process for a single middleware class is the following:
__init__method triggered (On server start-up).
__call__method triggered (On every request).
- If declared,
- View method starts with
- If declared,
process_exception()method triggered when exception occurs in view.
- View method finishes.
- If declared,
process_template_response()triggered when view returns