Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

in path django.utils.deprecation.py we have some class about deprecation warning for methods.

in that file we have a class called MiddlewareMixin. this class used to write middleware classes. Although not related to deprecation, Why this class wrote in this path?

like image 638
vorujack Avatar asked Oct 21 '18 08:10

vorujack


1 Answers

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 django-1.10), 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.

like image 95
Willem Van Onsem Avatar answered Sep 19 '22 01:09

Willem Van Onsem