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对象或等价方法)
复制代码
posted @ 2019-04-08 21:15  截击机1  阅读(82)  评论(0编辑  收藏  举报