Bird
Raised Fist0
Djangoframework~3 mins

Why Request/response middleware flow in Django? - Purpose & Use Cases

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
The Big Idea

Discover how one simple flow can save you from repeating the same code everywhere!

The Scenario

Imagine you have to check every incoming web request for security, log details, and modify responses manually in every view function.

The Problem

Doing these checks and changes manually in each view is repetitive, error-prone, and easy to forget, leading to inconsistent behavior and bugs.

The Solution

Django's request/response middleware flow lets you write reusable code that automatically processes requests before views and responses after views, keeping your code clean and consistent.

Before vs After
Before
def view(request):
    if not check_security(request):
        return error_response()
    log_request(request)
    response = do_view_logic(request)
    response = modify_response(response)
    return response
After
class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if not self.check_security(request):
            return self.error_response()
        self.log_request(request)
        response = self.get_response(request)
        response = self.modify_response(response)
        return response
What It Enables

This flow enables you to add features like security, logging, and response tweaks in one place that applies to all requests automatically.

Real Life Example

For example, a middleware can add a security token check to every page request without changing each view, making your site safer effortlessly.

Key Takeaways

Manual request handling is repetitive and risky.

Middleware centralizes request and response processing.

This keeps your Django app clean, consistent, and easier to maintain.

Practice

(1/5)
1. What is the main purpose of middleware in Django's request/response flow?
easy
A. To directly render HTML templates
B. To run code before and after the view processes a request
C. To manage database migrations
D. To handle user authentication only

Solution

  1. Step 1: Understand middleware role

    Middleware runs code before and after views to modify requests or responses.
  2. Step 2: Compare options

    Only To run code before and after the view processes a request describes this behavior; others describe unrelated tasks.
  3. Final Answer:

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

    Middleware = pre/post view code [OK]
Hint: Middleware wraps views to add pre/post processing [OK]
Common Mistakes:
  • Confusing middleware with template rendering
  • Thinking middleware manages database directly
  • Assuming middleware only handles authentication
2. Which of the following is the correct minimal structure of a Django middleware class?
easy
A. def my_middleware(get_response): def middleware(request): return get_response(request) return middleware
B. class MyMiddleware: def process_request(self, request): pass
C. class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response
D. class MyMiddleware: def handle(self, request): return request

Solution

  1. Step 1: Recall Django middleware class pattern

    Middleware must have __init__ with get_response and __call__ with request.
  2. Step 2: Match options to pattern

    Only class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response matches this exact structure; others miss __call__ or use wrong methods.
  3. Final Answer:

    Class with __init__ and __call__ methods -> Option C
  4. Quick Check:

    Middleware class = __init__ + __call__ [OK]
Hint: Middleware class needs __init__ and __call__ methods [OK]
Common Mistakes:
  • Using process_request instead of __call__
  • Defining middleware as a simple function without class
  • Missing get_response parameter in __init__
3. Given this middleware code, what will be printed when a request is processed?
class LogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        print('Init called')
    def __call__(self, request):
        print('Before view')
        response = self.get_response(request)
        print('After view')
        return response

# Assume this middleware is active and a request comes in
medium
A. Init called\nBefore view\nAfter view
B. Before view\nAfter view\nInit called
C. After view\nBefore view\nInit called
D. Init called only

Solution

  1. Step 1: Understand middleware instantiation

    __init__ runs once when server starts, printing 'Init called'.
  2. Step 2: Trace __call__ during request

    On request, prints 'Before view', calls view, then prints 'After view'.
  3. Final Answer:

    Init called\nBefore view\nAfter view -> Option A
  4. Quick Check:

    Init once, then before/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 prints
  • Ignoring that __call__ wraps the view call
4. Identify the error in this middleware code snippet:
class ExampleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        response = self.get_response
        return response
medium
A. Missing parentheses when calling get_response in __call__
B. Missing __init__ method
C. Using wrong method name instead of __call__
D. Returning request instead of response

Solution

  1. Step 1: Check __call__ method

    It assigns response = self.get_response without calling it (missing parentheses).
  2. Step 2: Understand consequence

    Without parentheses, response is a function, not a response object, causing errors.
  3. Final Answer:

    Missing parentheses when calling get_response in __call__ -> Option A
  4. Quick Check:

    Call get_response() with () [OK]
Hint: Always call get_response with parentheses in __call__ [OK]
Common Mistakes:
  • Forgetting parentheses on function calls
  • Confusing method names
  • Returning request instead of response
5. You want to add a custom header 'X-Hello: World' to every response using middleware. Which code correctly implements this?
hard
A. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response.header['X-Hello'] = 'World' return response
B. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): request['X-Hello'] = 'World' response = self.get_response(request) return response
C. class HeaderMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) response.add_header('X-Hello', 'World') return response
D. class HeaderMiddleware: 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: Recall how to add headers in Django response

    Response objects support dict-like access to headers: response['Header-Name'] = value.
  2. Step 2: Check options for correct header addition

    class HeaderMiddleware: 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 uses response['X-Hello'] = 'World' correctly after calling get_response.
  3. Final Answer:

    response['X-Hello'] = 'World' after getting the response -> Option D
  4. Quick Check:

    Use response['Header'] = value to add headers [OK]
Hint: Add headers by setting response['Header'] = value after get_response [OK]
Common Mistakes:
  • Trying to add headers to request object
  • Using non-existent add_header method
  • Accessing headers attribute which doesn't exist on response