Django Middleware

Manish Sangwan   31 January,2020  

In this post we will discuss the following.

  • What is a middleware
  • When to use middleware
  • Things to remember when writing middleware
  • Writing some middleware’s to understand how order of middleware matters

What is a middleware

  • Middleware’s are hooks to modify Django request or response object.
  • Middleware is a lightweight plugin that processes during request and response execution.
  • Middleware is used to perform a function in the application. The functions can be a security, session, csrf protection, authentication etc.
  • Django provides various built-in middleware and also allows us to write our own middleware. See, settings.py file of Django project that contains various middleware, that is used to provides functionalities to the application. For example, Security Middleware is used to maintain the security of the application.

When to use middleware

  • You can use middleware if you want to modify the request i.e HttpRequest object which is sent to the view. Or you might want to modify the HttpResponse object returned from the view. Both these can be achieved by using a middleware.
  • You might want to perform an operation before the view executes. In such case you would use a middleware.
  • Django provides some default middleware. eg: AuthenticationMiddleware
  • Very often you would have used request.user inside the view. Django wants user attribute to be set on request before any view executes. Django takes a middleware approach to accomplish this. So Django provides an AuthenticationMiddleware which can modify the request object.

Things to remember when using middleware

  • Order of middleware’s is important.
  • A middleware only needs to extend from class object.
  • A middleware is free to implement some of the methods and not implement other methods.
  • A middleware may implement process_request but may not implement process_response and process_view. Infact it is very common and lot of Django provided middlewares do it.
  • A middleware may implement process_response but not implement process_request.

Writing some middleware’s

Make sure you have a Django project with a url and a view, and that you are able to access that view.

Create a file middleware.py in any of your app.

I have an app called lms and so I am writing this in books/middleware.py

Middleware can live anywhere on your Python path.

__init__(get_response)

Middleware factories must accept a get_response argument. You can also initialize some global state for the middleware. Keep in mind a couple of caveats:

Django initializes your middleware with only the get_response argument, so you can’t define __init__() as requiring any other arguments.

Unlike the __call__() method which is called once per request, __init__() is called only once, when the Web server starts.

Activating middleware

To activate a middleware component, add it to the MIDDLEWARE list in your Django settings.

In MIDDLEWARE, each middleware component is represented by a string: the full Python path to the middleware factory’s class or function name.

For example, here’s the default value created by django-admin startproject:

Middleware order and layering

During the request phase, before calling the view, Django applies middleware in the order it’s defined in MIDDLEWARE, top-down.

You can think of it like an onion: each middleware class is a “layer” that wraps the view, which is in the core of the onion. If the request passes through all the layers of the onion (each one calls get_response to pass the request in to the next layer), all the way to the view at the core, the response will then pass through every layer (in reverse order) on the way back out.

If one of the layers decides to short-circuit and return a response without ever calling its get_response, none of the layers of the onion inside that layer (including the view) will see the request or the response. The response will only return through the same layers that the request passed in through.

Now, Make request to any url. This should get printed on runserver console

0
Like