DJango middleware learning

Posted by Kaylub on Tue, 08 Mar 2022 03:45:54 +0100

1. What is middleware and how it works

A mechanism of embedding the hook / response in the middleware. It is an underlying plug-in system that can modify the global input and output of django.

let me put it another way

The working principle of HTTP Web server is generally to accept the request sent by the user and then give a response. Django is no exception. Its general working method is to accept the request object and other parameters, submit them to the view for processing, and then give its response data: rendered html file or json format data.

However, in actual work, it is not to hand over the request object to the special function or class for processing immediately after receiving the request object, nor to return the response to the user immediately after the view is executed.

In fact, Django initially accepted the HttpRequest object instead of the request object. It is the role of the middleware to package the HttpRequest object and the user object into a global variable request object, so that you can use request as a variable in the view or call request casually in the template user

The role of Middleware in the request/response processing mechanism of django is as follows:

HttpRequest - Middleware  - View  - Middleware  -  HttpResponse

It is precisely because a request HttpRequest needs to be processed by the middleware before being passed to the view for processing, and the response processed by the view can only be returned to the user after being processed by the middleware. We can write our own middleware to realize permission verification, limit user requests, print logs, change output content and other application scenarios, such as:

 

  • Users with specific IP addresses or users who are not logged in are prohibited from accessing our view view function
  • Limit the number of requests sent per unit time of the same IP address
  • Record the user's IP address before the View function is executed
  • Pass additional variables or parameters before the View function executes
  • Print specific information to the log before or after the View function is executed
  • After the View function is executed, modify the response data and return it to the user

It is worth mentioning that the middleware changes the input or output of django globally, and vice versa. If you want to make global changes to the input or output of django, you need to use middleware.

For example, @ login_ The required decorator requires users to log in before accessing our view function. Imagine that we have a website where most of the view functions require users to log in. Each view function needs to be preceded by @ login_ The required decorator is a silly behavior. With the help of middleware, we can realize the global implementation without using decorator;

Only login users can access the view function, and anonymous users jump to the login page. The implementation principle is also very simple: before a request reaches the view function, we first check the request Judge whether the user has passed the verification, and then jump.

In addition, Django's global verification of the CSRF token carried in the Post form is also carried out through the middleware csrfViewMiddleware, rather than through a single decorator.

Introduction to Django's own 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',
]

 

  • SecurityMiddleware: it provides several security improvements for request/response, without which it is unsafe
  • SessionMiddleware: enable session support, no session without it
  • CommonMiddleware: Based on APPEND_SLASH and prepend_ Rewrite the URL according to the settings of www. If APPEND_SLASH is set to true, and the initialization URL does not end with a slash, and the corresponding definition is not found in URLconf. At this time, a new URL ending with a slash is formed; If prepend_ If WWW is set to true, the URL missing www. will be redirected to the same URL that starts with www.
  • CsrfViewMiddleware: add the protection of cross site request forgery. Add a hidden form word short to the POST form, and check whether there is a correct value in the request. Without it, there is no Csrf protection
  • AuthenticationMiddleware: add the HttpRequest attribute to each received user object before the execution of the view function, indicating the currently logged in user.
  • MessageMiddleware: enable cookie and session based message support
  • Xframeoptions middleware: protection of click hijacking.

If you want to implement the whole site cache, you also need to use UpdateCacheMiddleware and FetchFromCacheMiddleware, but you must pay attention to their order. Update comes first and Fetch comes last.

 

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]

In addition, Django also provides GzipMiddleware for compressing website content, localeMiddleware that returns different content according to user request language and ConditionalGetMiddleware that attaches conditions to GET request. These middleware are optional.

Middleware execution sequence of Django

When you're in settings When registering the middleware, py must consider the execution order of the middleware. The middleware is executed from top to bottom before the request reaches the view, and the response process is executed from bottom to top after the view is executed.

Custom Middleware

To customize the middleware, you must first create a new file Middleware in the directory where the app belongs Py, add the intermediate code, and then in the project settings Py, add it to the list of middleware for registration, and pay attention to the order when adding. Django provides two forms of writing custom middleware: function and class. The basic framework is as follows:

Function implementation

def simple_middleware(get_response):
# One-time configuration and initialization.  One time setup and initialization

    def middleware(request):
        # Code to be executed for each request before
# the view (and later middleware) are called.
        # The request reaches the code before the view function is executed

        response = get_response(request)

        # Code to be executed for each request/response after
        # the view is called.  Code after view function execution

        return response

    return middleware

Class implementation

class SimpleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization. One time setup and initialization

    def __call__(self, request):
        # Code to be executed for each request before
# the view (and later middleware) are called.
        # Code before view function execution

        response = self.get_response(request)

        # Code to be executed for each request/response after
        # the view is called.  Code after view function execution

        return response

Applied to practical cases. We write a MyFirstMiddleware, which involves the whole process of django's request/response, prints out the request execution process, and prints out whether the user logs in before the view function:

class MyFirstMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization. One time setup and initialization

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.
        print("Received request Request, the view function will be executed immediately")
        if not request.user.is_authenticated:
            print("The requested user is not logged in")

        response = self.get_response(request)
        # Code to be executed for each request/response after
        # the view is called.  Code after view function execution
        print("The execution of the view function is over and ready to provide a response")

        return response

In settings Py, the last middleware is customized, and the app name is users

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',
    'users.middleware.MyFirstMiddleware',
]

Because our customized middleware depends on the request object, we must put it behind the AuthenticationMiddleware. After registering the middleware, if you run Python manage Py runserver and you will see the output.

 

Thanks for learning website: https://mp.weixin.qq.com/s?__biz=MjM5OTMyODA4Nw==&mid=2247484447&idx=1&sn=1c8292f771ae69e7b7313d46a9fb212f&chksm=a73c6427904bed315f108724384a1f3c134ec1bc2dd09d08f5227b0debbfd219fd0864f48fe2&scene=21#wechat_redirect