Bird
Raised Fist0
Djangoframework~5 mins

Creating custom middleware in Django

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction

Middleware lets you add extra steps to handle web requests and responses. Custom middleware helps you add your own special rules or actions in your Django app.

You want to log every request made to your website.
You need to check user permissions before views run.
You want to modify response headers for all pages.
You want to measure how long each request takes.
You want to block certain IP addresses from accessing your site.
Syntax
Django
class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Code before view runs
        response = self.get_response(request)
        # Code after view runs
        return response

The __init__ method runs once when the server starts.

The __call__ method runs for each request.

Examples
This middleware prints the URL path of every request.
Django
class SimpleLogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        print(f"Request path: {request.path}")
        response = self.get_response(request)
        return response
This middleware adds a custom header to every response.
Django
class AddHeaderMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        response["X-Custom-Header"] = "Hello"
        return response
Sample Program

This middleware measures how long each request takes and prints it in the console.

Django
import time

class TimerMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        start = time.time()
        response = self.get_response(request)
        duration = time.time() - start
        print(f"Request took {duration:.4f} seconds")
        return response
OutputSuccess
Important Notes

Always add your custom middleware class to the MIDDLEWARE list in settings.py.

Middleware runs in the order listed in MIDDLEWARE.

Be careful with code in middleware to avoid slowing down requests.

Summary

Middleware lets you run code before and after views.

Custom middleware is a class with __init__ and __call__ methods.

Add your middleware to MIDDLEWARE in settings to activate it.

Practice

(1/5)
1. What is the main purpose of custom middleware in Django?
easy
A. To run code before and after a view processes a request
B. To define database models
C. To create HTML templates
D. To handle user authentication only

Solution

  1. Step 1: Understand middleware role

    Middleware runs code before and after views handle requests.
  2. Step 2: Compare options

    Only To run code before and after a view processes a request describes middleware's purpose correctly; others describe unrelated tasks.
  3. Final Answer:

    To run code before and after a view processes a request -> Option A
  4. Quick Check:

    Middleware = pre/post view code [OK]
Hint: Middleware runs code around views, not models or templates [OK]
Common Mistakes:
  • Confusing middleware with models or templates
  • Thinking middleware only handles authentication
  • Believing middleware runs only after views
2. Which method must a Django custom middleware class implement to process requests and responses?
easy
A. __call__
B. __init__
C. process_request
D. handle_request

Solution

  1. Step 1: Recall middleware class structure

    Custom middleware uses __init__ for setup and __call__ to handle requests and responses.
  2. Step 2: Identify correct method for processing

    __call__ is the method that processes requests and responses; others are incorrect or deprecated.
  3. Final Answer:

    __call__ -> Option A
  4. Quick Check:

    Middleware processing method = __call__ [OK]
Hint: Use __call__ to process requests in custom middleware [OK]
Common Mistakes:
  • Using process_request which is old style
  • Confusing __init__ with request processing
  • Inventing non-existent methods like handle_request
3. Given this middleware code, what will be printed when a request is processed?
class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        print('Middleware initialized')

    def __call__(self, request):
        print('Before view')
        response = self.get_response(request)
        print('After view')
        return response
medium
A. After view\nBefore view\nMiddleware initialized
B. Middleware initialized\nBefore view\nAfter view
C. Before view\nAfter view\nMiddleware initialized
D. Middleware initialized only

Solution

  1. Step 1: Understand when __init__ runs

    __init__ runs once when middleware is created, printing 'Middleware initialized'.
  2. Step 2: Trace __call__ execution order

    __call__ prints 'Before view', calls the view, then prints 'After view'.
  3. Final Answer:

    Middleware initialized\nBefore view\nAfter view -> Option B
  4. Quick Check:

    Init then before and after view prints [OK]
Hint: Init prints once; __call__ prints before and after view [OK]
Common Mistakes:
  • Thinking __init__ runs on every request
  • Mixing order of print statements
  • Ignoring that __call__ wraps the view call
4. What is wrong with this custom middleware code?
class MyMiddleware:
    def __init__(self):
        pass

    def __call__(self, request):
        response = self.get_response(request)
        return response
medium
A. No error, code is correct
B. __call__ should not return a response
C. Missing get_response parameter in __init__
D. Middleware classes cannot have __call__ method

Solution

  1. Step 1: Check __init__ signature

    Middleware __init__ must accept get_response parameter to store it for later use.
  2. Step 2: Identify missing attribute

    get_response is used in __call__, but not saved in __init__, causing an error.
  3. Final Answer:

    Missing get_response parameter in __init__ -> Option C
  4. Quick Check:

    __init__ needs get_response [OK]
Hint: Always accept get_response in __init__ for middleware [OK]
Common Mistakes:
  • Omitting get_response parameter
  • Not storing get_response as instance variable
  • Thinking __call__ cannot return response
5. You want to create a custom middleware that adds a header 'X-Hello: World' to every response. Which code snippet correctly implements this?
hard
A. class HelloMiddleware: def __init__(self, get_response): self.get_response = get_response def process_response(self, request, response): response['X-Hello'] = 'World' return response
B. class HelloMiddleware: def __init__(self): pass def __call__(self, request): response = self.get_response(request) response.headers.add('X-Hello', 'World') return response
C. class HelloMiddleware: def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response
D. class HelloMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response

Solution

  1. Step 1: Confirm __init__ accepts get_response

    class HelloMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response correctly accepts and stores get_response in __init__.
  2. Step 2: Check __call__ modifies response

    class HelloMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response calls get_response, adds header, and returns response properly.
  3. Step 3: Identify errors in other options

    class HelloMiddleware: def __init__(self): pass def __call__(self, request): response = self.get_response(request) response.headers.add('X-Hello', 'World') return response misses get_response in __init__; class HelloMiddleware: def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response misses __init__; class HelloMiddleware: def __init__(self, get_response): self.get_response = get_response def process_response(self, request, response): response['X-Hello'] = 'World' return response uses old process_response method not supported in new style middleware.
  4. Final Answer:

    class HelloMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response['X-Hello'] = 'World' return response -> Option D
  5. Quick Check:

    New middleware = __init__ + __call__ + modify response [OK]
Hint: New middleware needs get_response in __init__ and modifies response in __call__ [OK]
Common Mistakes:
  • Omitting get_response in __init__
  • Using old process_response method
  • Trying to add headers before calling get_response