Bird
Raised Fist0
Djangoframework~30 mins

Creating custom middleware in Django - Try It Yourself

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
Creating custom middleware
📖 Scenario: You are building a Django web application that needs to log every request's path for debugging purposes.
🎯 Goal: Create a custom middleware that logs the request path each time a user visits any page.
📋 What You'll Learn
Create a middleware class named LogRequestMiddleware
Add an __init__ method that accepts get_response
Implement a __call__ method that logs the request path using print
Return the response from the middleware
Add the middleware to the MIDDLEWARE list in settings.py
💡 Why This Matters
🌍 Real World
Custom middleware is useful for adding features like logging, authentication checks, or modifying requests and responses in Django applications.
💼 Career
Understanding middleware helps you customize request handling and is a common task in Django web development jobs.
Progress0 / 4 steps
1
Create the middleware class
Create a class called LogRequestMiddleware with an __init__ method that takes get_response as a parameter and stores it as an instance variable.
Django
Hint

Remember, the __init__ method sets up the middleware with the next callable.

2
Add the __call__ method
Add a __call__ method to LogRequestMiddleware that takes request as a parameter and calls self.get_response(request) to get the response.
Django
Hint

The __call__ method processes the request and returns the response.

3
Log the request path
Inside the __call__ method, before calling self.get_response(request), add a print statement that outputs "Request path:" followed by request.path.
Django
Hint

Use print("Request path:", request.path) to log the path.

4
Add middleware to settings
In settings.py, add the string 'your_app.middleware.LogRequestMiddleware' to the MIDDLEWARE list.
Django
Hint

Insert 'your_app.middleware.LogRequestMiddleware' at the end of the MIDDLEWARE list.

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