zoukankan      html  css  js  c++  java
  • django—中间件

    中间件

    Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。每个中间件都可以完成特定的功能。

    中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性,其它的MVC框架也有这个功能,名称为IoC

    中间件在哪里?

    在settings.py 我们可以看到:

    这些字符串,就是一个一个的类。它们就是中间件。

    中间件的方法

    中间件可以定义五个方法,分别是:(主要的是process_request和process_response)

    • process_request(self,request)
    • process_view(self, request, view_func, view_args, view_kwargs)
    • process_template_response(self,request,response)
    • process_exception(self, request, exception)
    • process_response(self, request, response)

    以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。

    五个方法

    1.处理请求前:在每个请求上,request对象产生之后,url匹配之前调用,返回None或HttpResponse对象。

    def process_request(self,request):

      pass

    2.处理视图前:在在每个请求上,url匹配之后,视图函数调用之前调用,返回None或HttpResponse对象。

    def process_view(self, request, view_func, view_args, view_kwargs):

      pass

    3.处理响应后:视图函数调用之后,所有响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse对象。

    def process_response(self, request, response):

      pass

    4.处理异常:只有当视图抛出异常时调用,在每个请求上调用,返回一个HttpResponse对象。

    def process_exception(self, request, exception):

      pass

    5.视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。

    def process_response(self, request, response):

      pass

    process_request

    process_request有一个参数,就是request,这个request和视图函数中的request是一样的。

    它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MyMiddle(MiddlewareMixin):
        def process_request(self, request):
            print("这是我的第一个中间件-----request----")
    
    
    class MyMiddle2(MiddlewareMixin):
    
        def process_request(self, request):
            print("这是我的第二个中间件-----request----")
            return

     去settings.py注册

    结果:

    这是我的第一个中间件-----request----
    这是我的第二个中间件-----request----

    注意:

    1  顺序是按中间件注册的顺序执行的。

    2 不同中间件之间传递的request都是同一个对象

    process_response

    它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MyMiddle(MiddlewareMixin):
        def process_request(self, request):
            print("这是我的第一个中间件-----request----")
    
        def process_response(self, request, response):
            print("这是我的第一个中间件-----response----")
            return response      #  必须返回的是HttpResponse对象
    
    
    class MyMiddle2(MiddlewareMixin):
    
        def process_request(self, request):
            print("这是我的第二个中间件-----request----")
            return
    
        def process_response(self, request, response):
            print("这是我的第二个中间件-----response----")
            return response

    结果:

    这是我的第一个中间件-----request----
    这是我的第二个中间件-----request----
    这是视图函数------view-------
    这是我的第二个中间件-----response----
    这是我的第一个中间件-----response----

    我们可以看到

    (1)它是在执行视图函数之后

    (2)注意它的执行顺序:倒序执行。也就是与注册中间件的顺序相反。

    process_view

    process_view(self, request, view_func, view_args, view_kwargs)

    该方法有四个参数

    request是HttpRequest对象。

    view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)

    view_args是将传递给视图的位置参数的列表.

    view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。

    Django会在调用视图函数之前调用process_view方法。

    它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。

    如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MyMiddle(MiddlewareMixin):
        def process_request(self, request):
            print("这是我的第一个中间件-----request----")
    
        def process_response(self, request, response):
            print("这是我的第一个中间件-----response----")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            """
            :param request:  浏览器发来的请求对象
            :param view_func: 将要执行的视图函数的名字
            :param view_args: 将要执行的视图函数的位置参数
            :param view_kwargs: 将要执行的视图函数的关键字参数
            :return:
            """
            print("这是我的第一个中间件----process_view-----")
            print(view_func)
    
    
    class MyMiddle2(MiddlewareMixin):
    
        def process_request(self, request):
            print("这是我的第二个中间件-----request----")
            return
    
        def process_response(self, request, response):
            print("这是我的第二个中间件-----response----")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("这是我的第二个中间件----process_view-----")
            print(view_func)

    结果:

    这是我的第一个中间件-----request----
    这是我的第二个中间件-----request----
    这是我的第一个中间件----process_view-----
    <function index at 0x000001B7CF806BF8>
    这是我的第二个中间件----process_view-----
    <function index at 0x000001B7CF806BF8>
    这是视图函数------view-------
    这是我的第二个中间件-----response----
    这是我的第一个中间件-----response----

    我们可以看到:

    (1)它的执行顺序与注册中间件的顺序一致,从上到下。

    (2)在执行视图函数之前

    process_exception

    process_exception(self, request, exception)

    该方法两个参数:

    一个HttpRequest对象

    一个exception是视图函数异常产生的Exception对象。

    这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,

    并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MyMiddle(MiddlewareMixin):
        def process_request(self, request):
            print("这是我的第一个中间件-----request----")
    
        def process_response(self, request, response):
            print("这是我的第一个中间件-----response----")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("这是我的第一个中间件----process_view-----")
            print(view_func)
    
        # 只有视图函数异常才会执行
        def process_exception(self, request, exception):
            print(exception)
            print("第一个中间件 中的process_exception")
    
    
    class MyMiddle2(MiddlewareMixin):
    
        def process_request(self, request):
            print("这是我的第二个中间件-----request----")
            return
    
        def process_response(self, request, response):
            print("这是我的第二个中间件-----response----")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("这是我的第二个中间件----process_view-----")
            print(view_func)
    
        def process_exception(self, request, exception):
            print(exception)
            print("第二个中间件 中的process_exception")

    结果:

    这是我的第一个中间件-----request----
    Traceback (most recent call last):
    这是我的第二个中间件-----request----
    这是我的第一个中间件----process_view-----
    <function index at 0x000001BEB3206BF8>
    这是我的第二个中间件----process_view-----
    <function index at 0x000001BEB3206BF8>
    这是视图函数------view-------
    ----------------------------------------------
    第二个中间件 中的process_exception
    第一个中间件 中的process_exception
    ----------------------------------------------
    这是我的第二个中间件-----response----
    这是我的第一个中间件-----response----

    可以看到:

    (1)执行顺序是倒序

    (2)在执行视图函数之后,返回响应之前

    中间的执行过程

    请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法,将HttpResponse对象返回给浏览器。也就是说:如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。

    process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。加入中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。

    process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/ykgo/p/9392111.html
Copyright © 2011-2022 走看看