Why middleware mixin declared in django.utils.deprecation.py Why middleware mixin declared in django.utils.deprecation.py python python

Why middleware mixin declared in django.utils.deprecation.py


In short: it is a tool to turn deprecated middleware into new one, although it has some limitations.

Django's middleware "style" has changed. This MiddlewareMixin can in most cases "convert" an old-styled middleware class to a new style middleware decorator, as is written in the documentation on Upgrading pre-Django 1.10-style middleware:

class django.utils.deprecation.MiddlewareMixin

(...)

In most cases, inheriting from this mixin will be sufficient to make an old-style middleware compatible with the new system with sufficient backwards-compatibility. The new short-circuiting semantics will be harmless or even beneficial to the existing middleware. In a few cases, a middleware class may need some changes to adjust to the new semantics.

In the "old days" (prior to ), middleware was written like:

class SomeMiddleware:    def process_request(self, request):        # ...        pass    def process_response(self, request, response):        # ...        return response

But nowadays, middleware is seen more as some sort of "decorator" around the "underlying middleware", and eventually the view. As specified in the documentation on the new middleware:

A middleware can be written as a function that looks like this:
def simple_middleware(get_response):    # One-time configuration and initialization.    def middleware(request):        # Code to be executed for each request before        # the view (and later middleware) are called.        response = get_response(request)        # Code to be executed for each request/response after        # the view is called.        return response    return middleware

By introducing a new "style", you can see the old middleware as "deprecated" itself, which is of course a pity because all middleware that was previously written now would be rendered invalid.

The MiddlewareMixin is however capable to convert such old middleware in modern middleware, it does this by overriding the __call__ function, and thus call the process_request and process_response in between, like we can see in the source code [GitHub]:

class MiddlewareMixin:    def __init__(self, get_response=None):        self.get_response = get_response        super().__init__()    def __call__(self, request):        response = None        if hasattr(self, 'process_request'):            response = self.process_request(request)        response = response or self.get_response(request)        if hasattr(self, 'process_response'):            response = self.process_response(request, response)        return response

Here we thus make the object callable by overriding the __call__ function, and thus mimicking how the def middleware(request) in the new style works. If however in the old middleware, the __call__ is overridden as well, then this can of course result in some problems. Furthermore the old style middleware had some functions like process_view, process_exception, and process_template_response, which are no longer used here. But I have the idea that these were not very "popular" anyway.