Django Component-Middleware

Keywords: Python Django Session

Django request execution flow chart:

 

middleware

The Concept of Middleware

Middleware, as its name implies, is a process between request and response processing, which is relatively lightweight and changes the input and output of django globally. Because the change is global, it needs to be used cautiously, and poor performance will be affected.

Django's official definition of middleware:

Middleware is a framework of hooks into Django's request/response processing. <br>It's a light, low-level "plugin" system for globally altering Django's input or output.

If you want to modify the request, for example, the HttpRequest object that is sent to the view. Or you want to modify the HttpResponse object returned by view, which can be implemented through middleware.

Maybe you want to do something before the view is executed, which can be done with middleware.

Django default Middleware:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
]

Each middleware has specific functions.

Custom Middleware

There are four methods in middleware:

 

process_request 

process_response

process_view

process_exception

 

process_request,process_response

 

When a user initiates a request, it passes through all the middleware in turn. At this time, the request is process_request, and finally reaches the function of views. After the view function is processed, it passes through the middleware in turn. At this time, it is process_response, and finally returns to the requester.

 

 

The middleware of the above pictures is the default of django. We can also define a middleware by ourselves. We can write a class by ourselves, but we must inherit Middleware Mixin.

First, create utils packages under app01 and middlewares.py files under the packages (which store the classes corresponding to custom middleware)

In middlewares.py:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print("Md1 request")
     #return HttpResponse("Prohibited")
    def process_response(self,request,response):
        print("Md1 Return")
        return response

class Md2(MiddlewareMixin):

    def process_request(self,request):
        print("Md2 request")
    def process_response(self,request,response):
        print("Md2 Return")
        return response

Add middleware Md1 and Md2 in settings:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
    'app01.utils.midddlewares.Md1', 
    'app01.utils.midddlewares.Md2',
]

With regard to the location of middleware Md1 and Md2, starting with the startup file, app01 and startup file are in the same directory, so app01.utils.midddlewares.Md1

In urls.py:

from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
]

views.py:

def index(request):

    print("view function...")
    return HttpResponse("OK")

Implementation results:

Md1 request
Md2 request
view function...
Md2 returns
Md1 returns

Execution process description: the user initiates the request, executes the process_request in Md1, prints the "Md1 request"; then executes the process_request in Md2, prints the "Md2 request"; finds the index view function through the index distributed by url routing, prints the "view function..." and returns the response object "OK" (the content to be displayed on the page in the future); and then executes the process_response in Md2 to print. "Md2 returns"; continue to execute the process_response in Md1, print "Md1 returns", and finally present the response content to the user.

Note: If the request arrives at the process_request in Md1 and returns directly unconditionally, that is, return HttpResponse("prohibition"), the program will send the request directly to the process_response in Md1 and return it to the requester in turn. The results are as follows:

"Ban" is displayed on the page and printed as follows:

Md1 request
Md2 request

The flow chart is as follows:

 

 

process_view:

process_view(self, request, callback, callback_args, callback_kwargs)

In the middlewares.py file:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print("Md1 request")
    def process_response(self,request,response):
        print("Md1 Return")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("Md1view")

class Md2(MiddlewareMixin):

    def process_request(self,request):
        print("Md2 request")
        return HttpResponse("Md2 interrupt")
    def process_response(self,request,response):
        print("Md2 Return")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("Md2view")

The results are as follows:

Md1 request
Md2 request
Md1view
Md2view
view function...
Md2 Return
Md1 Return

The analysis process chart is as follows:

 

After the url request comes in, the process_request function of middleware 1 and 2 will be executed. After the execution of the two requests, the routing distribution will return to the process_view of middleware 1 when the process_request of the last middleware reaches the routing mapping. Then it will go down to the views function in turn, and finally return to the arrival function in turn through the process_response. Households.

Since process_view is after routing control, the view function can be invoked at the process_view level.

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print("Md1 request")
        #return HttpResponse("Md1 interrupt")
    def process_response(self,request,response):
        print("Md1 Return")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):

        # return HttpResponse("hello")

        response=callback(request,*callback_args,**callback_kwargs)
        return response

The results are as follows:

Md1 request
Md2 request
view function...
Md2 returns
Md1 returns

Note: If process_view has a return value, it will go over other process_view and view functions, but all process_response s will be executed.

process_exception:

process_exception(self, request, exception)

The example is modified as follows:

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print("Md1 request")
        #return HttpResponse("Md1 interrupt")
    def process_response(self,request,response):
        print("Md1 Return")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):

        # return HttpResponse("hello")

        # response=callback(request,*callback_args,**callback_kwargs)
        # return response
        print("md1 process_view...")

    def process_exception(self, request, response):
        print("md1 process_exception...")



class Md2(MiddlewareMixin):

    def process_request(self,request):
        print("Md2 request")
        # return HttpResponse("Md2 interrupt")
    def process_response(self,request,response):
        print("Md2 Return")
        return response
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("md2 process_view...")

    def process_exception(self, request, response):
        print("md2 process_exception...")

When there is no error in the view function:

Md1 request
Md2 request
md1 process_view...
md2 process_view...
view function...

Md2 Return
Md1 Return

When views.py goes wrong, the flow chart is as follows:

 

When the view function fails:

Md1 request
Md2 request
md1 process_view...
md2 process_view...
view function...
md2 process_exception...
md1 process_exception...
Md2 Return
Md1 Return

Application case

1. Do IP Access Frequency Limitation

Some IP access servers are too frequent to intercept, such as limiting access to no more than 20 times per minute.

2. URL Access Filtering

If the user accesses the login view (leave it alone)

If you want to access other views, you need to check whether there is session authentication. You have already released it, and you have not returned login, so you don't need to write decorators on multiple view functions!

 

 

 

Author: Wanderers

Date: 2019-10-03

Posted by Rabea on Wed, 09 Oct 2019 20:39:21 -0700