Bird
Raised Fist0
Djangoframework~10 mins

Request/response middleware flow in Django - Step-by-Step Execution

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
Concept Flow - Request/response middleware flow
Incoming HTTP Request
Middleware 1: process_request
Middleware 2: process_request
View Function Called
Middleware N: process_response
Middleware N-1: process_response
Middleware 1: process_response
HTTP Response Sent Back
The request passes through middleware in order before reaching the view, then the response passes back through middleware in reverse order before sending to client.
Execution Sample
Django
def middleware_1(get_response):
    def middleware(request):
        print('Middleware 1: before view')
        response = get_response(request)
        print('Middleware 1: after view')
        return response
    return middleware
This middleware prints messages before and after the view is called, showing request and response flow.
Execution Table
StepActionMiddleware LayerMessage PrintedFlow Direction
1Request entersMiddleware 1Middleware 1: before viewDown (request)
2Request passesMiddleware 2Middleware 2: before viewDown (request)
3Request reachesViewView processes requestDown (request)
4Response returnsMiddleware 2Middleware 2: after viewUp (response)
5Response returnsMiddleware 1Middleware 1: after viewUp (response)
6Response sentClientNo messageEnd
💡 Response sent back to client after passing all middleware in reverse order
Variable Tracker
VariableStartAfter Middleware 1 RequestAfter Middleware 2 RequestAfter ViewAfter Middleware 2 ResponseAfter Middleware 1 ResponseFinal
requestIncoming HTTP request objectPassed to Middleware 1Passed to Middleware 2Received by ViewPassed back Middleware 2Passed back Middleware 1Sent to client
responseNoneNoneNoneView returns responseMiddleware 2 modifies/forwardsMiddleware 1 modifies/forwardsFinal HTTP response
Key Moments - 2 Insights
Why does the response go through middleware in reverse order?
Because middleware wraps the view call like layers of an onion, the request goes in order, but the response comes back out in reverse order, as shown in execution_table steps 4 and 5.
What happens if a middleware returns a response before calling get_response?
The middleware short-circuits the flow and the view and later middleware are skipped. This is not shown in the table but is important to know.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what message is printed at step 2?
AMiddleware 1: after view
BMiddleware 2: before view
CView processes request
DMiddleware 2: after view
💡 Hint
Check the 'Message Printed' column for step 2 in the execution_table
At which step does the response start going back up through middleware?
AStep 4
BStep 3
CStep 1
DStep 6
💡 Hint
Look for 'Flow Direction' changing to 'Up (response)' in execution_table
If Middleware 1 returned a response immediately without calling get_response, what would change in the execution_table?
AStep 5 would be skipped
BStep 1 would be skipped
CSteps 2 and 3 would be skipped
DNo steps would change
💡 Hint
Think about which middleware and view are bypassed if response is returned early
Concept Snapshot
Django middleware wraps request and response.
Request flows through middleware in order before view.
Response flows back through middleware in reverse order.
Middleware can modify request or response.
Middleware can short-circuit by returning response early.
Full Transcript
In Django, when a web request comes in, it passes through each middleware's request processing in order. Each middleware can inspect or change the request. After all middleware have processed the request, the view function runs to generate a response. Then the response goes back through the middleware in reverse order, allowing each middleware to modify the response before it is sent to the client. This flow is like layers wrapping around the view. Middleware can also stop the flow early by returning a response without calling the next layer. This trace shows the messages printed at each middleware step and how the request and response move through the layers.

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