Suppose I have the following class, as inspired by the Django documentation:
class SimpleMiddleware(object): def __ init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response def process_view(self, request, view_func, view_args, view_kwargs): return None
When reading Daniel Rubio's book 'Beginning Django', he explains that the order of execution is:
__ init __
method triggered (on server startup)__ call __
method triggered (on every request)process_view()
method triggeredself.get_response(request)
statement in __ call __
What exactly does "__ call __
method triggered (on every request)" mean? Does not 'triggering' the __ call __
method actually trigger 'self.get_respone(request)
' automatically, thus calling either another middleware or a class?
The Django documentation states that:
process_view()
is called just before Django calls the view.`
To me, this would have to mean that Django checks if the instance of the 'SimpleMiddleware'
class contains a method 'process_view()'
and then triggers that, before moving on to calling the __ call __()
method, which 'calls the view'? Otherwise, if the __ call __
method is triggered immediately, won't 'process_view()
' be missed since the __ call __
method calls the view (or the next middleware)?
Could someone please help me understand the execution process? How does Django go about this?
Thank you
You are mixing up old style (pre django 1.10) and new style middlewares. The new style looks as follows:
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# do stuff with request
response = self.get_response(request)
# do stuff with request and/or response
return response
The old style equivalent of that was:
class SimpleMiddleware:
def process_request(self, request):
# do stuff with request
def process_response(self, request, response):
# do stuff with request and/or response
In order to make it easier to port old code to the new way of doing things, django has added the MiddlewareMixin (source):
class MiddlewareMixin:
def __init__(self, get_response=None):
self.get_response = get_response
super().__init__()
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
response = response or self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
All you have to do now with your old style middlewares is to make them subclass this mixin. But generally, new style middlewares do not per se have or need the process_...
methods. But e.g.:
from django.utils.deprecation import MiddlewareMixin
class SimpleMiddleware(MiddlewareMixin):
def process_request(self, request):
# do stuff with request
def process_response(self, request, response):
# do stuff with request and/or response
will work in both worlds.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With