Middleware in Django

Learn via video courses
Topics Covered

Django Middleware is an essential component of the Django web framework, functioning as a lightweight, low-level plugin system. It seamlessly integrates into the request/response cycle, allowing for global modifications of incoming and outgoing requests. This flexible framework supports a range of operations like security, authentication, session management, and CSRF protection. Middleware components, implemented as Python classes, are defined in the MIDDLEWARE list in the project's settings.py file. Django not only offers built-in middleware but also enables developers to craft custom middleware solutions, enhancing the framework's adaptability and functionality.

How Does It Work?

Well, the order in which we define the middleware classes is extremely important. The Middleware classes are processed sequentially that is from top-down during the request cycle, which means the execution of SecurityMiddleware will take place, then SessionMiddleware, and finally XFrameOptionsMiddleware. It will run the process_request() and process_view() functions for each Middleware. After this, Django will work on the view function. It will deliver a response to the client whenever the task is completed.

During the response cycle, the Middleware classes are processed bottom-up, which means at first the execution of XFrameOptionsMiddleware will take place, then MessageMiddleware, and finally SecurityMiddleware. It will run the process_exception(), process_template_response(), and process_response() functions for each Middleware. Finally, Django will provide the client with the response. Any combination of synchronous and asynchronous requests can be supported via middleware. If it cannot handle both, Django will modify requests to suit the middleware's specifications, but at a performance cost.

Creating a Custom Middleware

A middleware class accepts the argument get_response and returns a response.

In the above code,

  • We have created a class MyCustomMiddleware.
  • We have created two functions __init__ and __call__.
  • __init__ function accepts the get_response argument because Django only uses it to initialize middleware. It is only called once the web server is started.
  • __call__ is called for each request.

Activating Middleware

To activate the middleware in our project we are supposed to add it in the settings.py file under the MIDDLEWARE section which consists of all the middleware in our project.

The MIDDLEWARE list may be empty but it is recommended to have at least the CommonMiddleware component.

Middleware Order and Layering

Middleware is applied in the order defined in the MIDDLEWARE list, with each middleware class acting as a layer. Each request is processed from top to bottom, and responses are delivered in reverse order.

Other Middleware Methods

We may add three additional ways to our middleware to expand its functionality, apart from request and response.

process_view(request, ViewFunc, ViewArgs, ViewKwargs )

It accepts an HttpRequest object, a function object, a list of arguments supplied to the view, or a dictionary of arguments. This method is called immediately before view. It returns either None or an HttpResponse; if a HttpResponse is returned, it terminates processing and returns the result.

process_template_response(request,response)

It accepts two arguments: an HttpRequest reference and an HttpResponse object. This function is called immediately after the view has completed execution unlike process_view in which the method is called before the view. It produces a response object with the render method implemented.

process_exception(request, exception)

It accepts two arguments: an HttpRequest object and an Exception class object generated by the view function. This method either returns None or a HttpResponse object. If it responds, the middleware is activated, and the result is returned to the browser.

Dealing with Streaming Responses

process_response

HttpRequest is the object request. The StreamingHttpResponse or HttpResponse object is the response returned by a Django view or middleware.

All responses are passed via process_response() before they are sent back to the web page.

It returns a StreamingHttpResponse or HttpResponse object. The messages we want to display can be sent as a response, as used in the example below. It may modify the existing response or generate and send back a new StreamingHttpResponse or HttpResponse.

The process_response() function is called every time, even if the process_view() and process_request() methods were missed. This means that our process_response() method cannot depend on the configuration made in process_request().

HttpResponse is used in the majority of Django responses. This means that the body of the response is created in memory and transmitted to the HTTP client as a single piece.

In the above code,

  • We created a function demo_view.
  • We store the message we want to display.
  • Content-Length defines the length of the data.
  • The function returns the response. A StreamingHttpResponse, on the other hand, is one in which the body of the response is provided to the client in several sections. To stream, a response from Django to the browser, use the StreamingHttpResponse class.

In the above code,

  • We have created a function greet.
  • Inside the function greet, we displayed the messages in sections using yield.
  • We have created a function at demo_view.
  • Inside the function demo_view, StreamingHttpResponse is returned with the function greet.

Exception Handling

The HttpRequest object is a request. The exception object is an exception the view function generates. Django executes process_exception(), as soon as an exception is generated by a view. process_exception() returns an HTTPResponse object or None. If a HttpResponse object is returned, the response middleware and template response will be used, and the browser will get the final response. Otherwise, the default exception handling is used. While in the response phase, middleware, including process_exception, is executed in reverse order. The middleware classes above that middleware are not called if an exception middleware responds.

Conclusion

Hello developer!! I am sure by now you must have understood what Django middleware is. Let us summarize what we have learned so far

  • Middleware is a framework that is attached to Django's request/response processing. It's a lightweight, low-level "plugin" framework for changing Django's input or output globally.
  • The components of middleware are a python class. Each of these components is in charge of completing a specific operation.
  • The process_request() and process_view() functions for each Middleware run during the request cycle.
  • The process_exception(), process_template response(), and process_response() functions for each Middleware run during the response cycle.
  • The MIDDLEWARE list may be empty but it is recommended to have at least a CommonMiddleware component.