中间件

django处理一个Request的过程是首先通过django 中间件,然后再通过默认的URL方式进行的。所以说我们要做的就是在django 中间件这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response,那么我们可以简化原来的设计思路,把中间件不能处理的 Request统统不管,丢给Django去处理

中间件的安装

直接在django配置里面添加如下配置,Django本来就配置类好多中间件,中间件的执行顺序从上到下依次进行

MIDDLEWARE = [
'md.middleware.M1',  # 自定义的中间件
'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已经帮我们规定好了

from django.utils.deprecation import MiddlewareMixin


class M1(MiddlewareMixin):
    # 方法和参数必须要按照人家的规定的写
    def process_request(self, request):
        print('process_request')  # 注意,request没有返回值

    def process_response(self, response):
        print('process_response')
        return response

这样,django运行起来之后会先打印process_request,然后执行视图函数,视图函数执行完毕之后最后执行M1里面的process_response方法,也就是打印process_response

注意:如果新版本的django不能导入中间件的话,完全可以自己写模块

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

将这段代码放到自己定义的中间键前面就可以了

中间件和装饰器的区别

中间件是针对所有的请求和返回,而装饰器只是针对某个函数的,装饰器的粒度更小一些

中间件的方法

Django的中间件就是一个类,类里面有五个方法

  • process_request 请求刚进来执行的方法,
  • process_response 请求回去的时候执行的方法,必须要有返回值
  • process_view 路由匹配,等最后一个request执行完毕后会跳到第一个路由匹配进行执行
  • process_exception 程序报错执行所有中间件的exception方法,从最后一个开始一直执行到第一个然后再返回到最后一个response执行
  • process_tempalte_response

方法返回值

  • process_request 此方法不能有返回值,如果有返回值会直接执行与他平行的response,下面的不会执行 ,但是也可以对请求值进行判断,然后相应的复合条件的返回,不符合条件的不返回,也可以return None,和没有返回值是一个效果

  • process_response 必须要有返回值,因为他就是请求返回的时候执行的,没有返回值一定会报错,但是我们可以对返回值进行一定的修改

  • process_view 如果有返回值,会跳到最后一个response返回

  • process_exception 如果某个中间件捕捉到错误且返回值的话,直接跳到最后一个response执行

应用场景

由于中间件的特性,他的应用很广也很灵活

用户验证

class M1(MiddlewareMixin):
    if request.path_info == '/login/':
            return None
    # 方法和参数必须要按照人家的规定的写
    def process_request(self, request):
        if not request.session.get('user_info'):
            return redirect('/login/')

    def process_response(self, response):
        print('process_response')
        return response

注意:

  1. 这个方法用到了session,session也是一个中间件,因此我们在安装这个中间件的时候必须要放在session中间件的下面,最好放在最下面

    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware', # session中间件
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'md.middleware.M1', # 放在session中间件下面
    ]

  2. 注意前面对request.path_info的判断,如果不加这个判断的话,跳转login页面的时候又会进行一次判断session,如果不符合继续跳转,就会形成死循环,加这个判断的一次是,如果判断当前路径为login的话返回None,也就是继续执行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容