What is Django middleware and how to Create a custom Django middleware

(Comments)

Middleware

As mentioned in the Django official docs, Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.

Each middleware component is responsible for doing some specific function. For example, Django includes a middleware component, AuthenticationMiddleware, that associates users with requests using sessions.

alt text

SecurityMiddleware, SessionMiddleware, CommonMiddleware, CsrfViewMiddleware, AuthenticationMiddleware are some the middleware classes provided by django.

Custom Middleware

In have an app called "music" and the models.py file looks like this.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.


class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

    def __unicode__(self):
        return self.first_name

Create a file called "custommiddleware.py" in the your app. For example, my custommiddleware.py file will be like this music/custommiddleware.py. Edit the file as shown below.

from .models import Musician


class GetGuitarists(object):
    def process_request(self, request):
        print "List of Guitarists"

Now in your settings.py file, edit the MIDDLEWARE and add our custom middleware GetGuitarists

MIDDLEWARE = [
    'music.custommiddleware.GetGuitarists',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Now run the server and open any url defined in your project. The string "List of Guitarists" will be printed in the terminal. Here is the sample terminal output.

Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
List of Guitarists

The order in which you add the middleware is important. For example in our current example, we have added our middleware at the topmost. If we edit our middleware code as shown below

from .models import Musician from django.utils.deprecation import MiddlewareMixin

class GetGuitarists(MiddlewareMixin):

    def process_request(self, request):
        print "List of Guitarists"
        print request.user

Now, if we open a url, we will get AttributeError. This is because the AuthenticationMiddleware is after the "custommiddleware" and so the user object is not yet added to the request. If we make the following changes to our code in settings.py , we will get the output as shown below.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'nestedblog.middleware.GetGuitarists',
]

Output in terminal:

List of Guitarists
AnonymousUser

So, the order of the middleware is important.

Let's see what happens if we return a HttpResponse in our custom middleware.

class GetGuitarists(MiddlewareMixin):

    def process_request(self, request):
        print "List of Guitarists"
        print request.user
        return HttpResponse("Execution stops after this.")

Output in terminal:

List of Guitarists
AnonymousUser

Your view will no more be executed and no matter which url you try, you will see "Execution stops after this." So if a Middleware's process_request() returns a HttpResponse object then process_request of any subsequent middlewares is bypassed. Also view execution is bypassed.

PROCESS_VIEW

Method: process_view(request, view_func, view_args, view_kwargs)

Neither view_args nor view_kwargs include the first view argument (request). process_view() is called just before Django calls the view. It should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other process_view() middleware and, then, the appropriate view.

If it returns an HttpResponse object, Django won’t bother calling any other view or exception middleware, or the appropriate view; it’ll apply response middleware to that HttpResponse, and return the result.

Comments

Recent Posts

Archive

2022
2021
2020
2019
2018
2017
2016
2015
2014

Tags

Authors

Feeds

RSS / Atom