2

I read the doc, then I could understand that we can define a function-based middleware and a class-based middleware in Django as shown below but I could not understand the difference between them. *I'm learning Middleware:

Function-Based Middleware:

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

Class-Based Middleware:

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

My questions:

  1. What is the difference between a function-based middleware and a class-based middleware in Django?

  2. Which should I use basically?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
  • From a functional point of view, there is no difference. Django does not care if it a class or a function. It will just perform `decorator = the_middleware(view_function)` to create the decorator, and then call `decorator(request)` when a request is fired. Whether that is done through an inner function or by using a `__call__` makes not much difference. – Willem Van Onsem Jun 13 '23 at 20:57

1 Answers1

2
  1. What is the difference between a function-based middleware and a class-based middleware in Django?

There is no difference as far as Django is concerned. When the server is initialized, it will construct some outer view function where each middleware basically decorates the inner one, so:

view_leveli = my_middleware(view_leveli1)

with view_leveli1 is one level "deeper" than view_leveli.

Then when a request is fired, it will eventually call the outer view, so:

view_leveln(request)

it will thus call the outer middleware that (likely) calls the middleware one level deeper that will then call another level deeper until eventually the inner level is triggered which will pass control to the view function.

But you can emulate this with all sorts of means. For example a:

class SimpleMiddleware:
    def __new__(cls, get_response):
        result = object.__new__(cls)
        result.get_response = get_response
        # one-time initialization
        return result.process_request

    def process_request(self, request):
        # process request
        return self.get_response(request)

This will work as well, since it basically provides the same "interface" necessary by Django.

  1. Which should I use basically?

Just like function-based views, and class-based views, likely for small ad-hoc tasks, the decorator (function-based approach) is a good idea.

If you define reusable components that can be subclasses, or with complicated data flows where you want define helper functions, a class-based view might be more appropriate.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555