Django—middleware

一、Django中间件的请求周期

我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下:

也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。

二、自定义及注册中间件

1. 创建中间件

在project根目录下创建中间件py文件:

class RequestExeute(object):
    def process_request(self, request):
        print('process_request')

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

    def process_exception(self, request, exception):
        """
        当views函数出错时执行
        :param request: 
        :param exception: 
        :return: 
        """
        print('process_exception')
        
    def process_response(self, request, response):
        """
        必须return HttpResponse
        :param request: 
        :param response: 
        :return: 
        """
        print('process_response')
        return response

    def process_template_response(self, request, response):
        """
        视图函数的返回值中,如果有render方法,才被调用
        :param request:
        :param response:
        :return:
        """
        print('process_template_response')
        return response
md.py

2. 注册中间件

在settings.py文件中,按照欲执行的顺序注册:

ps. 在1.9及之前的版本中,中间件的关键字为:MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
    'zqxt.middleware.BlockedIpMiddleware',
    ...其它的中间件
)

三、中间件中方法的执行顺序

1. 正常状况

from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
    def process_request(self, request):
        print('m1.request')
        # return HttpResponse('request_m1')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('m1.view')
        # response = callback(request, *callback_args, **callback_kwargs)
        # return response

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

    def process_exception(self, request, exception):
        print('m1.process_exception')
        return HttpResponse('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.request')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('m2.view')
        # response = callback(request, *callback_args, **callback_kwargs)
        # return response

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

    def process_exception(self, request, exception):
        print('m2.process_exception')
        return HttpResponse('m2.process_exception')

    def process_template_response(self, request, response):
        """
        视图函数的返回值中,如果有render方法,才被调用
        :param request:
        :param response:
        :return:
        """
        print('m2.process_template_response')
        return response
process_request和process_view返回None

执行顺序:

  1. m1.request
  2. m2.request
  3. m1.view
  4. m2.view
  5. m2.response
  6. m1.response

2. 在版本1.10及之后

若process_request返回HttpResponse 对象,则从当前中间件的process_response向前返回

from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
    def process_request(self, request):
        print('m1.request')
        return HttpResponse('request_m1')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('m1.view')
        # response = callback(request, *callback_args, **callback_kwargs)
        # return response

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

    def process_exception(self, request, exception):
        print('m1.process_exception')
        return HttpResponse('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.request')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('m2.view')
        # response = callback(request, *callback_args, **callback_kwargs)
        # return response

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

    def process_exception(self, request, exception):
        print('m2.process_exception')
        return HttpResponse('m2.process_exception')

    def process_template_response(self, request, response):
        """
        视图函数的返回值中,如果有render方法,才被调用
        :param request:
        :param response:
        :return:
        """
        print('m2.process_template_response')
        return response


# class RequestExeute(object):
#     def process_request(self, request):
#         print('process_request')
#
#     def process_view(self, request, callback, callback_args, callback_kwargs):
#         print('process_view')
#
#     def process_exception(self, request, exception):
#         """
#         当views函数出错时执行
#         :param request:
#         :param exception:
#         :return:
#         """
#         print('process_exception')
#
#     def process_response(self, request, response):
#         """
#         必须return HttpResponse
#         :param request:
#         :param response:
#         :return:
#         """
#         print('process_response')
#         return response
#
#     def process_template_response(self, request, response):
#         """
#         视图函数的返回值中,如果有render方法,才被调用
#         :param request:
#         :param response:
#         :return:
#         """
#         print('process_template_response')
#         return response
M1的process_request返回HttpResponse

执行顺序:

  1. m1.request
  2. m1.response

process_view与process_request类似:

from django.shortcuts import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
    def process_request(self, request):
        print('m1.request')
        # return HttpResponse('request_m1')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('m1.view')
        response = callback(request, *callback_args, **callback_kwargs)
        return response

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

    def process_exception(self, request, exception):
        print('m1.process_exception')
        return HttpResponse('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.request')

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print('m2.view')
        # response = callback(request, *callback_args, **callback_kwargs)
        # return response

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

    def process_exception(self, request, exception):
        print('m2.process_exception')
        return HttpResponse('m2.process_exception')

    def process_template_response(self, request, response):
        """
        视图函数的返回值中,如果有render方法,才被调用
        :param request:
        :param response:
        :return:
        """
        print('m2.process_template_response')
        return response
m1的process_view返回HttpResponse

执行顺序:

  1. m1.request
  2. m2.request
  3. m1.view
  4. m2.response
  5. m1.response

 

 3. 在版本1.10之前

若process_request返回HttpResponse 对象,则当前中间件之后的process_request都不会执行,而从最后一个中间件的process_response向前返回

 

参考资料:

1. Python之路【第十六篇】:Django【基础篇】

2. http://code.ziqiangxuetang.com/django/django-middleware.html

posted @ 2018-02-27 11:20  dion至君  阅读(99)  评论(0)    收藏  举报