The original is from understanding Django Middlewares, which describes the middleware definition, function, and how to write middleware –orangleliu in general.
Note: Middleware and middleware have the same meaning in the following article, not completely translated
Let's say you've read the middleware section of the Django official documentation. The knowledge mentioned in the documentation is described in as much detail as possible, but I hope you are familiar with the middleware
basic concepts.
In this article we will discuss the following:
- What is middleware
- When to use middleware
- We write what middleware must remember.
- Write some middlewares to understand the work process and essentials of middleware
What is middleware
Middlewares is a hook that modifies a Django request or response object. The following is a description of the Django document.
aofintoasystemforor output.
When to use middleware
If you want to modify the request, such as the HttpRequest object that is transferred to the view. Or you want to modify the HttpResponse object returned by the view, which can be implemented through middleware.
You might also want to do something before the view executes, which can be done with middleware.
Django provides some default middleware, such as:
AuthenticationMiddleware
You may use it frequently in view request.user
. Django wants to set the user to the request property before each view executes, so it uses a middleware to achieve this goal. So Django provides the middleware that can modify the request object AuthenticationMiddleware
.
Django modifies the request object in this way:
https://github.com/django/django/blob/master/django/contrib/auth/middleware.py#L22
For example, you have an app whose users are people in different time zones. You want them to be able to display the correct time zone when they visit any page, so that all views can get the user's own timezone information. In this case you can use the session to solve, so you can add a middleware like this:
class TimezoneMiddleware(object): def process_request(self, request): # Assuming user has a OneToOneField to a model called Profile # And Profile stores the timezone of the User. request.session[‘timezone‘] = request.user.profile.timezone
Timezonemiddleware is dependent on Request.user, Request.user is set by AuthenticationMiddleware
. So in
settings.MIDDLEWARE_CLASSES
Configuration, Timezonemiddleware must be after authenticationmiddleware.
The following example gives you more experience with the middleware order.
What to remember when using middleware
- The order of middlewares is very important.
- A middleware only needs to inherit the object class
- A middleware can implement some methods and do not need to implement all the methods
- A middleware can implement Process_request (methods) but cannot implement Process_response (methods) and Process_view methods. These are common and Django offers a lot of middlewares can do.
- A middleware can implement the Process_response method, but there is no need to implement the Process_request method
The Authenticationmiddleware only implements the processing of the request and does not handle the response. Reference Document
Gzipmiddleware only implements the processing of the response, and does not implement the request and view processing see the documentation
Write some Middlewares
First make sure you have a Django project that requires a URL and a view, and can enter this view. Below we will do a few tests on request.user, confirm that the permissions are set up, and can print the Request.user information correctly in view.
Create a middleware.py file in any app.
I have an app called books, so the location of the file isbooks/middleware.py
class BookMiddleware(object): def process_request(self, request): print"Middleware executed"
Add this middleware in middleware_classes
MIDDLEWARE_CLASSES = ( ‘books.middleware.BookMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,)
To send a request to any URL, the following information will be printed on the Runserver console.
Middleware executed
Modify the BookMiddleware.process_request
following
class BookMiddleware(object): def process_request(self, request): print"Middleware executed" print request.user
Accessing a URL again will cause an error.
‘WSGIRequest‘object‘user‘
This is because the request object has not set the user property yet.
Now let's change the order of the middlewares and BookMiddleware
put it AuthenticationMiddleware
behind.
MIDDLEWARE_CLASSES = ( ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘books.middleware.BookMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,)
To access a url,runserver console, print the following
Middleware executed<username>
This shows that middlewares processes the request in the order followed by settings. The order listed in the middleware_classes is consistent.
You can further confirm that middleware.py adds another middleware
class AnotherMiddleware(object): def process_request(self, request): print"Another middleware executed"
and add it to theMIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES = ( ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘books.middleware.BookMiddleware‘, ‘books.middleware.AnotherMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,)
Now the output is:
Middleware executed<username>Another middleware executed
Return HttpResponse in the Process_request method and change the Bookmiddleware to the following:
class BookMiddleware(object): def process_request(self, request): print"Middleware executed" print request.user return HttpResponse("some response")
Try any of the following URLs and you will get the following output:
Middleware executed<username>
You will notice the following 2 things:
- No matter which URL you visit, your own view processing method is not executed, only "some response" such a response.
- Anothermiddleware.process_request not being executed
So if the HttpResponse object is returned in the Process_request method of middleware, then the middleware behind it will be skipped, and the processing method in view is skipped.
So it's rarely done in actual projects (but there are some projects, such as acting as agents).
Comment out "return HttpResponse("some response")"
, two middleware can handle the request normally.
Using Process_response
Add a Process_response method to these two middleware
class anothermiddleware(object): def process_request(self, request): Print "Another middleware executed" def process_response(self, request, response): Print "Anothermiddleware process_response executed" returnResponse class bookmiddleware(object): def process_request(self, request): Print "Middleware executed" PrintRequest.userreturnHttpResponse ("Some response")#self. _start = Time.time () def process_response(self, request, response): Print "Bookmiddleware process_response executed" returnResponse
Access some URLs to get the following output
Middleware executed<username>Another middleware executedAnotherMiddleware process_response executedBookMiddleware process_response executed
AnotherMiddleware.process_response()
Executed BookMiddleware.process_response()
prior to execution AnotherMiddleware.process_request()
BookMiddleware.process_request()
. So process_response()
the order of execution is exactly the opposite of Process_request. process_response()
The order of execution is executed from the last middleware, to the penultimate, and then to the first middleware.
Process_view
The way Django executes the middleware sequentially process_view()
, from top to bottom. Similar to the order in which the Process_request () method executes.
So if any one process_view()
returns the HttpResponse object, it will be omitted after it process_view()
, and will not be executed.
[Django advanced] Understanding the middleware mechanism and execution order in Django