Innovate anywhere, anytime withruncode.io Your cloud-based dev studio.
Django

Understanding Middleware Functionality in Django2.0

2022-07-25

Middlewares are used to modify the request object which is sent to the view or to modify the response object returned from the view. They allow us to modify request/response globally.

Django's old-style middleware:

Prior to Django 1.10, there were 5 hooks. Any class that implements process_request(), process_view(), process_exception(), process_template_response() and process_response() methods can act as a middleware and all of these are specified in the setting MIDDLEWARE_CLASSES.

The first two methods - process_request(), process_view() are executed before the execution of the view. The next three methods, process_exception(), process_template_response() and process_response() are executed after view returns the response object.

Django's new-style middleware:

The most important change you need to do when upgrading to Django 2.0 is to change MIDDLEWARE_CLASSES to MIDDLEWARE in settings.py file. In django 2.0 support for old-style middleware using settings.MIDDLEWARE_CLASSES is removed.

The old middleware must be a class where as the new middleware is any callable, which takes a get_response callable and returns a callable that takes the request and returns a response. These middlewares should be specified in MIDDLEWARE setting.

class TimeStampMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request.timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
        response = self.get_response(request)
        return response

Note: Here the get_response can be either the view that returns the response or the next middleware in the list. Hence the request is processed in the specified order of the middleware and the response in the reverse order.

To activate your custom middleware, you should just add the middleware path in MIDDLEWARE setting.

MIDDLEWARE = [
    '...',
    'my_app.middleware.TimeStampMiddleware',
    '...',
]

Upgrading from old style middleware:

Django provides django.utils.deprecation.MiddlewareMixin which must be extended by the old-style middleware. So that, MiddlewareMixin will convert the class object into a callable.

We can change existing middleware to extend MiddlewareMixin to work in Django 2.0 as follows:

from django.utils.deprecation import MiddlewareMixin

class CustomMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # Process the request
        pass

    def process_response(self, request, response):
        # Process the response
        return response

Inheriting from this MiddlewareMixin will make an old-style middleware compatible with the new system.