zoukankan      html  css  js  c++  java
  • Django 之 中间件

    一、概念

    1、什么是中间件?

      官方解释:中间件是用来处理Django的请求和响应的框架级别的钩子。基于全局范围产生影响。

      平民解释:中间件是帮助我们在视图函数执行前和执行后做的操作。它本质上就是一个自定义类,类中定义了几个方法,Django框架会在处理请求的特定的时间去执行这些方法。其余request请求,终于response请求。

    2、中间件在Django项目中Settings.py文件的配置

      

    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',
    ]

      MIDDLEWARE配置项是一个列表,列表中是一个个字符串,这些字符串其实是一个一个的类,也就是一个一个的中间件。

    3、自定义中间件

      1、中间件可以定义五个方法,分别是:

        1、process_request(self,request)        处理请求的方法

        2、process_view(self,request,view_func,view_args,view_kwargs)        处理视图的方法

        3、process_template_response(self,request,response)  处理模板的方法

        4、process_exception(self,request,exception)  处理异常的方法

        5、process_response(self,request,response)  处理响应的方法

      以上方法的返回值可以使None,或者是HttpResponse对象,如果是None,就按照自定义的中间件的方法继续向下执行,直到process_response方法执行结束,如果是HttpResponse对象,就直接将这个对象返回给用户。

    二、五种自定义中间件

      1、process_request

      自定义一个中间件的示例

        1、在APP下创建一个py文件,在py文件中定义中间件

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MD1(MiddlewareMixin):
    
        def process_request(self, request):            #  process_request方法 
            print("MD1里面的 process_request")      # 此时没有返回值 依次向下执行
    
        def process_response(self, request, response):       # process_response方法
            print("MD1里面的 process_response")
            return response
    class MD2(MiddlewareMixin):
    
        def process_request(self, request):            #  process_request方法 
            print("MD2里面的 process_request")      # 此时没有返回值 依次向下执行
    
        def process_response(self, request, response):       # process_response方法
            print("MD2里面的 process_response")
            return response

        2、需要在setting.py中的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',
        'middlewares.MD1',  # 自定义中间件MD1
        'middlewares.MD2'  # 自定义中间件MD2
    ]

        3、当浏览器发送了请求之后,Django服务器响应请求,返回给浏览器。此时终端打印出如下内容:

    MD1里面的 process_request
    MD2里面的 process_request
    app01 中的 index视图

        4、如果把MD1he MD2在setting.py中的顺序调换一下,打印内容就是如下:

    MD2里面的 process_request
    MD1里面的 process_request
    app01 中的 index视图

        因此,process_request的执行顺序是按照注册顺序执行的。且是在视图函数执行前执行的。

        5、总结:

          1、中间件的process_request方法是在执行视图函数之前执行的。

          2、当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,从上到下依次执行。

          3、不同中间件之间传递的request都是同一个对象。从请求开始到响应结束,request都是同一个对象。

          4、如果内部有返回 HttpResponse对象,则不去执行视图函数,而是直接跳过所有的中间环节,执行process_response方法,以及其前边的方法。

      2、process_response

        1、示例

      

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MD1(MiddlewareMixin):     # 中间件MD1
    
        def process_request(self, request):           # process_response方法
            print("MD1里面的 process_request")
    
        def process_response(self, request, response):
            print("MD1里面的 process_response")
            return response
    
    
    class MD2(MiddlewareMixin):     # 中间件MD2
        def process_request(self, request):
            print("MD2里面的 process_request")
    
        def process_response(self, request, response):
            print("MD2里面的 process_response")
            return response
    
    # 每个类都是一个中间件

        2、process_response(self,request,response)有两个参数,request就是一个请求对象,response是视图函数放给的HttpResponse对象。该方法的返回值,也就是直接在中间件中写的返回值也必须是HttpResponse对象。

        3、访问视图函数,即匹配URL之后,执行视图函数。打印如下内容

    MD2里面的 process_request
    MD1里面的 process_request
    app01 中的 index视图
    MD1里面的 process_response
    MD2里面的 process_response

        如图所示:process_response方法是在视图函数执行之后,执行的。并且当有多个process_response方法时,按照 注册顺序的倒叙执行。

      3、process_view

        1、处理视图的函数

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

          该方法有四个参数

          1.request是HttpRequest对象

          2.view_func 是Django使用的视图函数。(它是实际的函数对象,而不是一个单纯的函数名字)。

          3.view_args是传递给视图函数的位置参数的元祖

          4.view_kwargs是传递给视图函数的关键字参数的字典

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

          他可以返回None或HttpResponse对象。如果返回None,继续向下执行,如果返回HttpResponse对象,将不再继续向下执行其他中间件中的process_view方法,而是直接执行process_response方法。

        3、示例

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MD1(MiddlewareMixin):
    
        def process_request(self, request):        # resquest 方法
            print("MD1里面的 process_request")
    
        def process_response(self, request, response):     # response 方法
            print("MD1里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):   # view方法
            print("-" * 80)
            print("MD1 中的process_view")
            print(view_func, view_func.__name__)
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2里面的 process_request")
    
        def process_response(self, request, response):
            print("MD2里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD2 中的process_view")
            print(view_func, view_func.__name__)

        输出结果

    MD2里面的 process_request
    MD1里面的 process_request
    --------------------------------------------------------------------------------
    MD2 中的process_view
    <function index at 0x000001DE68317488> index
    --------------------------------------------------------------------------------
    MD1 中的process_view
    <function index at 0x000001DE68317488> index
    app01 中的 index视图
    MD1里面的 process_response
    MD2里面的 process_response

        由图可知:process_view方法是在process_request之后,视图函数之前,并且按照注册顺序的正序执行。

      4、process_exception

        1、处理异常的方法

        2、参数

        process_exception(self,request,exception)

          1、HttpRequest对象

          2、视图函数异常时产生的Exception对象

        3、只有当视图函数异常时才会执行。如果返回只是None,就继续向下执行,如果返回值是一个HttpResponse对象,则不再继续向下执行其他的中间件的process_exception方法,而是直接执行process_response方法。且如果有多个中间件的时候,按照注册顺序的倒叙执行。

        4、示例

    from django.utils.deprecation import MiddlewareMixin
    
    
    class MD1(MiddlewareMixin):
    
        def process_request(self, request):
            print("MD1里面的 process_request")
    
        def process_response(self, request, response):
            print("MD1里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD1 中的process_view")
            print(view_func, view_func.__name__)
    
        def process_exception(self, request, exception):
            print(exception)
            print("MD1 中的process_exception")
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2里面的 process_request")
    
        def process_response(self, request, response):
            print("MD2里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD2 中的process_view")
            print(view_func, view_func.__name__)
    
        def process_exception(self, request, exception):
            print(exception)
            print("MD2 中的process_exception")

        打印结果

    MD2里面的 process_request
    MD1里面的 process_request
    --------------------------------------------------------------------------------
    MD2 中的process_view
    <function index at 0x0000022C09727488> index
    --------------------------------------------------------------------------------
    MD1 中的process_view
    <function index at 0x0000022C09727488> index
    app01 中的 index视图
    呵呵
    MD1 中的process_exception
    MD1里面的 process_response
    MD2里面的 process_response

        注意,这里没有执行MD2中的process_exception方法,因为MD1中的process_exception方法已经返回了响应对象。

       5、process_template_response

        1、参数:

            process_template_response(self,request,response)

            一个是HttpRequest对象,response是一个TemplateResponse对象。

        2、process_template_response是在视图函数执行完成之后立即执行的,但是前提条件是,视图函数返回的对象有一个render()方法

        3、示例

    class MD1(MiddlewareMixin):
    
        def process_request(self, request):
            print("MD1里面的 process_request")
    
        def process_response(self, request, response):
            print("MD1里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD1 中的process_view")
            print(view_func, view_func.__name__)
    
        def process_exception(self, request, exception):
            print(exception)
            print("MD1 中的process_exception")
            return HttpResponse(str(exception))
    
        def process_template_response(self, request, response):
            print("MD1 中的process_template_response")
            return response
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2里面的 process_request")
    
        def process_response(self, request, response):
            print("MD2里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD2 中的process_view")
            print(view_func, view_func.__name__)
    
        def process_exception(self, request, exception):
            print(exception)
            print("MD2 中的process_exception")
    
        def process_template_response(self, request, response):
            print("MD2 中的process_template_response")
            return response

         views.py中

    def index(request):
        print("app01 中的 index视图")
    
        def render():
            print("in index/render")
            return HttpResponse("O98K")
        rep = HttpResponse("OK")
        rep.render = render
        return rep

        4、输出结果

    MD2里面的 process_request
    MD1里面的 process_request
    --------------------------------------------------------------------------------
    MD2 中的process_view
    <function index at 0x000001C111B97488> index
    --------------------------------------------------------------------------------
    MD1 中的process_view
    <function index at 0x000001C111B97488> index
    app01 中的 index视图
    MD1 中的process_template_response
    MD2 中的process_template_response
    in index/render
    MD1里面的 process_response
    MD2里面的 process_response

        试图执行完成之后,立即执行process_template_response方法,顺序是倒叙执行。先执行MD1,再执行MD2,接着执行视图函数的HttpResponse对象的render方法,返回一个新的HttpResponse对象,接着执行中间件的process_response方法。

  • 相关阅读:
    四则运算2设计思路
    关于这个学期的读书计划
    关于20分钟没写出来程序思路的原因
    软件工程理论方法与实践
    员工类
    除的类
    基类
    乘的类
    减的类
    加的类
  • 原文地址:https://www.cnblogs.com/wf123/p/9794683.html
Copyright © 2011-2022 走看看