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

    一. 中间件

    中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,全局控制django输入和输出的钩子, 
      钩子:功能写上就自动运行,注释就不执行该功能
      # 由于是在全局上改变的,所以要慎用(高手可自行忽略这句)

    django中的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',
    ]

      从上图可以看出来,按照请求的顺序,在视图函数执行之前进行一些操作,可以在中间件中搞事情, 按照响应顺序,在视图函数执行之后进行一些操作,也可以在中间件中搞事情.

    # Django中用的wsgi是wsgiref是python标准库提供的模块,性能比较低,开发使用 ,性能高的是uwsgi,在进行项目部署的时候会用的到

    二 . 自定义中间件

      中间件可以定义五个方法: (主要是process_requestprocess_response)

    1. process_request(self,request)
    2. process_view(self,request,view_func,view_args,view_kwagrs)
    3. process_template_response(self,request,response)
    4. process_exception(self,request,exception)
    5. process_response(self,request,response)
    # 以上方法的返回值可以是None或者是HttpResponse对象, 如果是None, 则继续按照Django定义的规则向后继续执行, 如果是HttpResponse对象,则直接返回给用户.

      当用户发起请求的时候会从上到下一次经过所有的中间件,这个时候的请求是process_request, 最后到达views的函数中,views处理后,再依次从下到上穿过中间件,这个时候是process_response,最后返还给请求者

      

      自定义中间件的具体操作

    1. 自己写一个类, 但是必须继承MiddlewareMinMixin
    2. 在项目中创建一个包,名字一般叫utils,表示一个公用的组件,创建一个py文件.

      示例

    from django.utils.deprecation import MiddlewareMixin
    
    class MD1(MiddlewareMixin):
        #自定义中间件,有request方法说明请求来了要处理,有response方法说明响应出去时需要处理,不是非要写这两个方法,
        如果你没写process_response方法,那么会一层一层的往上找,哪个中间件有process_response方法就将返回对象给哪个中间件
    def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response

     

      process_request

    1.process_request有一个参数,就是request,这个request和视图函数中的request是一样的.
    2.它的返回值可以是None,也可以是HttpResponse对象,返回值是None的话,按照正常流程继续走,交给下一个中间件处理,
      如果是HttpResponse对象,Django将不执行视图函数,而将相应的对象返回给浏览器

      

      多个中间件是Django执行process_request的示例

    from django.utils.deprecation import MiddlewareMixin
    
    class MD1(MiddlewareMixin):
    
        def process_request(self, request):
            print("MD1里面的 process_request")
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2里面的 process_request")

      定义两个中间件,我们需要把它们加入到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',
        'utils.middlewares.MD1',  # 自定义中间件MD1,这个写的是所在路径,
        'utils.middlewares.MD2'  # 自定义中间件MD2
    ]

      我们开始访问一个视图,终端打印的是:

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

      由此可知,中间件是在视图函数之前执行,并且这个request就相当于一个接力棒一样,我用完了给你你才能用,一共就一个request.

      process_response

    from django.utils.deprecation import MiddlewareMixin
    
    class MD1(MiddlewareMixin):
        def process_request(self, request):
            print("MD1里面的 process_request")
            #不必须写return值
    
        def process_response(self, request, response):#request和response两个参数必须有,名字随便取
            print("MD1里面的 process_response")
            #print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容的方法
         return response  #必须有返回值,写return response  ,这个response就像一个接力棒一样
            #return HttpResponse('瞎搞') ,如果你写了这个,那么你视图返回过来的内容就被它给替代了
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2里面的 process_request")
    
        def process_response(self, request, response): #request和response两个参数必须要有,名字随便取
            print("MD2里面的 process_response") 
            return response  #必须返回response,不然你上层的中间件就没有拿到httpresponse对象,就会报错

      访问一个视图,看看终端的输出:

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

      

       

    有了中间件,我们在做大量的同样的操作的时候只需要在中间件里搞一下就好,比如在做session认证的时候,不需要在用装饰器一个一个的加了,
      但是这个中间件一定要放在Django自带的那个session的中间件的下面,因为我们要用到里面功能. 一定要注意放的顺序

      session认证的中间件示例

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse,redirect,render
    from django.urls import reverse
    
    class M1(MiddlewareMixin):
    
        def process_request(self, request):
    
            #设置路径白名单,只要访问的是login登陆路径,就不做这个session认证
            if request.path in [reverse('login'),]:
                return None   # 继续往下执行
            else:
                ret = request.session.get('session_login')
                if ret:
                    return None
                else:
                    return redirect(reverse('login'))
    
        def process_response(self, request, response):
            print('M1响应部分')
            # print(response.__dict__['_container'][0].decode('utf-8'))
            return response
           

       process_view

    process_view(self, request, view_func, view_args, view_kwargs)
    参数分别代表的意义
    1. request 是HttpRequest对象.
    2. view_func 就是你在网页上输入网址,然后url调用的那个函数
    3. view_args 是将要传递给视图函数的位置参数列表
    4. view_args 是将要传递给视图的关键字参数的字典
    
    # Django会在调用视图函数之前调用process_view方法

          

       process_exception

    process_exception(self, request, exception)
    参数的意义
    1. request 是HttpResponse对象
    2. exception 是视图函数异常产生的Exception对象.
    
    # 这个方法只有在视图函数出现异常才执行, 他的返回值可以是None或者是HttpResponse对象,
      如果返回的是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,
      如果返回的是None,将交给下一个中间件的process_exception方法来处理,执行顺序是注册顺序的倒序,
      如果都没有返回HttPResponse对象,那么Django就会给你返回一个,就是那个大黄页.

          

      process_template_response(用的比较少)

    process_template_response(self,request,response)
    request是HttpResponse对象
    response是TemplateResponse对象(由视图函数或者中间件产生)
    
    # process_template_response是在视图函数执行完成后立即执行,在模板渲染之前,
      但是他有一个前提条件,就是视图函数返回的对象有一个render()方法(或者表明该对象是TemplateResponse对象或等价方法)

      

  • 相关阅读:
    UI 简单练习(联动实例)
    软件工程与计算机科学
    中文编程
    自我介绍
    曾经的梦想
    即时通讯研究学习
    即时通讯研究学习
    创业
    2015-08-12-火影
    看<后海不是海>的随想
  • 原文地址:https://www.cnblogs.com/attila/p/10497435.html
Copyright © 2011-2022 走看看