Django中间件 ---- 第19章

文章目录

            • 1. 中间件执行流程
            • 2. 中间件原理浅析
            • 3. 中间件的应用

1. 中间件执行流程

Django 1.10之前,请求到达第一个中间件,会找到最后一个中间件的 process_response 返回:
Django中间件 ---- 第19章_第1张图片

而Django 1.10之后,会找到自己的 process_response 返回:
Django中间件 ---- 第19章_第2张图片

中间件是有序执行的!

2. 中间件原理浅析

中间件是类,首先查看Django源码中的中间件:
Django中间件 ---- 第19章_第3张图片
Django中间件 ---- 第19章_第4张图片
所以,我们写的中间件也要继承MiddlewareMixin类,这里把中间件类写在middleware.py,并放置在与manage.py同级目录下:

middleware.py:

from django.utils.deprecation import MiddlewareMixin

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

    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_response(self, request, response):
        print('m2.process_response')
        return response
"""
m1.process_request
m2.process_request
test
m2.process_response
m1.process_response
"""

还要在配置文件 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.M1',
    'middleware.M2'
]

可以看到 先执行process_request再执行process_response。还有个process_view方法:

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')
        # return callback(*callback_args, **callback_kwargs)

    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')
        # return callback(*callback_args, **callback_kwargs)

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

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

process_request有返回值会直接执行自己的process_response。如果执行的是process_view有返回值,会跳过下一个中间件的process_view,执行视图函数(这里是自动调用的)。接下来,不是执行自己的process_response返回给用户,而是 最开始 的process_response(把所有的process_response都执行一遍):

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(callback, callback_args, callback_kwargs) # () {}
        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_response(self, request, response):
        print('m2.process_response')
        return response
        
"""
m1.process_request
m2.process_request
m1.process_view
test
m2.process_response
m1.process_response
"""

中间件的类中还有 process_exception 方法,这是关于异常的方法。为了进行测试首先在视图函数中使代码产生异常:

def test(request):
    print('test')
    a = int('erics')
    return HttpResponse()

通过下面的代码测试发现,请求经过所有的process_request、process_view到达视图函数,没有错误的情况下会执行process_response,出现错误会执行process_exception在执行process_response:

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(callback, callback_args, callback_kwargs) # () {}
        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

    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')

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

在process_exception使用HttpResponse函数返回异常,可以看这个时候中间件方法的执行顺序:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

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

    def process_view(self, request, callback, callback_args, callback_kwargs):
        # print(callback, callback_args, callback_kwargs) # () {}
        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

    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')
        return HttpResponse('出现异常!')

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

异常被M2的process_exception处理了,跳过M1的process_exception,直接执行process_response。页面也不没有报错了:
在这里插入图片描述
中间件中还有process_template_response方法,但是这个方法在视图函数的返回值中有render方法才会执行,没有render方法不会被执行,所以这里修改视图函数:

class Foo:
    def __init__(self, req):
        self.req = req

    def render(self):
        return HttpResponse()

def test(request):
    obj = Foo(request)
    return obj

接下来可以看到process_template_response方法被执行,

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

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')

    def process_template_response(self, request, response):
        """
        视图函数的返回值中有render方法才会执行
        :param request:
        :param response:
        :return:
        """
        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):
        return HttpResponse('出现异常!')

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

"""
m1.process_request
m2.process_request
m1.process_view
m2.process_view
m2.process_template_response
m1.process_template_response
m2.process_response
m1.process_response
"""

process_template_response方法的使用,可以帮助我们把一些可以复用的功能组件拆分出来,如JSON序列化:

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

    def render(self):
        import json
        ret = {
            'status': self.status,
            'msg': self.msg
        }
        return HttpResponse(json.dumps(ret))

def test(request):
    return Foo(request, True, '错误信息!')

在视图函数中打造功能,改造另外一个对象,让这个对象把我们的数据封装起来:

class JsonResponse:
    """
    内部帮助我们序列化,
    """
    def __init__(self, req, status, msg):
        self.req = req
        self.status = status
        self.msg = msg

    def render(self):
        import json
        ret = {
            'status': self.status,
            'msg': self.msg
        }
        return HttpResponse(json.dumps(ret))


def test(request):
    return JsonResponse(request, True, '错误信息!')

视图函数返回的对象且对象中有render方法才会执行process_template_response方法。

3. 中间件的应用

中间件可以对 所有请求或一部分请求做批量处理。使用缓存时,需要对 所有请求进行判断,缓存中如果有就把缓存中的数据返回,没有就执行视图函数。对所有的请求进行判断就需要使用到中间件。

你可能感兴趣的:(Django)