Django-中间件-middleware

 中间件:

  中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。 
  每个中间件都会负责一个功能,例如,AuthenticationMiddleware,与sessions处理相关。

  适用于对所有请求以及部分内容做批量处理,例如缓存、

 配置中间件

  在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件。

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',
]
django.middleware.clickjacking.XFrameOptionsMiddleware

  浏览器访问的过程是发送request请求,然后返回一个response, 这个请求传递到 Django的过程如下:

 

 

 

 

 

  每一个中间件都是一个类,而当客户端对服务器发送请求的时候,首先会顺序执行中间件list中的每一个元素中的process_request函数,最后通过路由系统执行请求url所对应的view中的function,执行完成后会返回一个response,然后再从中间件列表中的最后一个元素的process_response开始,依次往上执行每一个元素中的process_response。

  

  而我们也可以在中间件列表中添加我们自定义的中间件

 自定义中间件:

1、创建中间件类:

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):  当process_request中有返回值的时候,会直接从自身的process_response依次向上执行
        print('m1.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):  当process_view函数中有返回的时候,会从中间件列表的最后一个元素的process_response函数依次向上执行
        print('m1.process_view')
        response=callback(request,*callback_args,**callback_kwargs)
        return response

    def process_response(self,request,response):
        print("m1.process_response")
        return response
  
class M2(MiddlewareMixin):
    def process_request(self,request):
        print('m2.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m2.process_view')

    def process_respones(self,request,response):
        print('m2.process_response')
        return response

2、注册中间件:

from django.middleware.common import CommonMiddleware
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',
    'md.M1',
    'md.M2',
]

3、views.py

from django.shortcuts import render,HttpResponse,redirect

def test (request): print("test") return HttpResponse("...")

 4、访问执行结果:

m1.process_request
m2.process_request
m1.process_view
test
m2.process_response
m1.process_response
 

 process_exception

views的函数中出现错误时,就会从中间件列表中的最后一个元素的process_exception方法开始执行,然后依次向上执行,直到执行到第一个的process_exception方法后,再从中间件列表中最后一个元素的process_response开始依次向上返回,顺序如上图所示。

如果在process_exception方法中有返回的话,则会停止向上执行 process_exception立刻从中间件列表中的最后一个元素的process_response依次向上返回。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Fade Zhao'

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_request(self,request):
        print('m1.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m1.process_view')
        
    def process_response(self,request,response):
        print("m1.process_response")
        return response

    def process_exception(self,request,exception):   #没有添加返回
        print('M1.process_exception')

class M2(MiddlewareMixin):
    def process_request(self,request):
        print('m2.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m2.process_view')

    def process_response(self,request,response):
        print('m2.process_response')
        return response
    def process_exception(self,request,exception):
        print('M2.process_exception')

views.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Fade Zhao'
from django.shortcuts import render,HttpResponse,redirect
def test (request):
    print("test")
    int('asdf')  #这导致报错
    return HttpResponse("........")

输出:

m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
M2.process_exception
M1.process_exception
Internal Server Error: /Family/test.html
Traceback (most recent call last):
.......报错信息......
m2.process_response
m1.process_response

在process_exception中添加返回值:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Fade Zhao'

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse,redirect

class M1(MiddlewareMixin):
    def process_request(self,request):
        print('m1.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m1.process_view')

    def process_response(self,request,response):
        print("m1.process_response")
        return response

    def process_exception(self,request,exception):
        print('M1.process_exception')
        return HttpResponse('出错了')  #在函数中添加返回

class M2(MiddlewareMixin):
    def process_request(self,request):
        print('m2.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m2.process_view')

    def process_response(self,request,response):
        print('m2.process_response')
        return response
    def process_exception(self,request,exception):
        print('M2.process_exception')
        return HttpResponse('出错了')    #添加返回

同样的views.py,访问后输出:

m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
M2.process_exception
m2.process_response
m1.process_response

 process_template_response:

process_template_response正常执行的话是不会调用,只有views函数的返回值对象中,如果有render()方法,这个函数才会被调用,

调用顺序和是先调用是

  views.function-->M2.process_template_response-->M1.process_template_response-->Foo.render-->M2.process_response-->M2.process_response

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Fade Zhao'

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse,redirect

class M1(MiddlewareMixin):
    def process_request(self,request):
        print('m1.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m1.process_view')

    def process_response(self,request,response):
        print("m1.process_response")
        return response

    def process_exception(self,request,exception):
        print('M1.process_exception',exception)
        return HttpResponse('出错了')

    def process_template_response(self,requset,response):
        print('M1.process_template_response')
        return response

class M2(MiddlewareMixin):
    def process_request(self,request):
        print('m2.process_request')

    def process_view(self,request,callback,callback_args,callback_kwargs):
        print('m2.process_view')

    def process_response(self,request,response):
        print('m2.process_response')
        return response
    def process_exception(self,request,exception):
        print('M2.process_exception',exception)
        return HttpResponse('出错了')
    def process_template_response(self,requset,response):
        '''
        视图函数的返回值对象中,如果有render方法,这个函数才会被调用
        '''
        print('M2.process_template_response')
        return response

views.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Fade Zhao'
from django.shortcuts import render,HttpResponse,redirect
import json


class Foo:
    def __init__(self, request, status, msg):
        self.request = request
        self.status = status
        self.msg = msg

    def render(self):  #在依次向上执行process_template_response后执行此函数
        print('Foo.render')
        ret = {
            'status': self.status,
            'msg': self.msg
        }
        ret = json.dumps(ret)
        return HttpResponse(ret)

def test (request):  
    print("test")
    obj = Foo(request,True,'欢迎新同学')   # 主要应用场景是在处理Ajax请求时,当做模板来使用
    return obj

输出:

m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
M2.process_template_response
M1.process_template_response
Foo.render
m2.process_response
m1.process_response

 

 

 

 

posted @ 2017-09-25 09:23  LeeeetMe  阅读(119)  评论(0编辑  收藏  举报