August Rush

一个还在努力成长的小火汁!

游龙当归海,海不迎我自来也。

We create our own demons.

You can reach me at augustrush0923@gmail.com
Django中间件钩子方法
发布:2021年04月21日 | 作者:augustrush | 阅读量: 318

process_view()

process_view(request, view_func, view_args, view_kwargs)

process_view()只在Django调用视图前被调用。

process_view()应该返回NoneHttpResponse对象。

如果它返回None,Django将继续处理这个请求,执行任何其他的process_view(),然后执行相应的视图。

如果它返回HttpResponse对象,Django不会去影响调用相应的视图;但它会将响应中间件应用到HttpResponse并返回结果。

例子:

# middlewares.py
class MyMiddleware2(MiddlewareMixin):
    def __init__(self, get_response):
        super(MyMiddleware2, self).__init__(get_response)
        print('MyMiddleware2 初始化执行')

    def process_request(self, request):
        print('MyMiddleware2 视图执行前执行一次')

    def process_response(self, request, response):
        print('MyMiddleware2 视图执行后执行一次')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        '''
        :param request: 浏览器发来的 request 请求对象
        :param view_func: 将要执行的视图函数的名字
        :param view_args: 将要执行的视图函数的位置参数
        :param view_kwargs: 将要执行的视图函数的关键字参数
        :return:
        '''
        print('MyMiddlware2 process_view执行了')
        print(f'request: {request} \nview_func: {view_func} \nview_args: {view_args} \nview_kwargs: {view_kwargs}')
        return HttpResponse("process_view 取代 view_func的HttpResponse返回")
# views.py

def test(request):
    print('test 视图函数执行')
    print(test)
    return HttpResponse("test HttpResponse 返回了。")

访问,http://127.0.0.1:8000/test/

运行结果:


程序执行流程

  1. 先执行所有中间件中的process_request方法---->
  2. 进行路由匹配---->
  3. 执行中间件中的process_view方法---->
  4. 执行对应的视图函数---->
  5. 执行中间件中的process_response方法---->

process_request只返回None时,都执行完之后,就匹配路由,找到要执行的视图函数,在执行视图函数之前先执行中间件的process_view函数

如果process_view也只返回None时,就继续执行后续的中间件的process_view方法,执行完所有的process_view函数之后就执行视图函数

如果其中有个process_view返回了HttpResponse,就不执行后续的process_view函数,会跳到process_response函数,并继续向上执行process_response函数

例如,中间件3的process_view返回了HttpResponse,就不再执行后续的中间件4,5,6的中间件了,直接跳到中间件6的process_response函数,并接着执行中间件5,4,3,2,1

如果有process_request函数返回了HttpResponse对象,就不执行后续的process_request函数,也不执行process_view函数,直接跳转到相应的process_response函数执行

例如,如果中间件2的process_request返回了HttpResponse,就不再往下执行process_request函数,也不执行process_view函数,直接跳转到中间2的process_response函数执行


process_exception()

process_exception(request, exception)

当视图引发异常时,Django才会调用process_exception()

process_exception()应该返回NoneHttpResponse对象。如果它返回一个HttpResponse对象,模板响应和响应中间件将被应用且会将结果响应返回浏览器。否则,就会开始默认异常处理。

# middlewares.py
class MyMiddleware1(MiddlewareMixin):
    def __init__(self, get_response):
        super(MyMiddleware1, self).__init__(get_response)
        print('MyMiddleware1 初始化执行')

    def process_request(self, request):
        print('MyMiddleware1 视图执行前执行一次')

    def process_response(self, request, response):
        print('MyMiddleware1 视图执行后执行一次')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MyMiddlware1 process_view执行了')

    def process_exception(self, request, exception):
        print('MyMiddleware1 process_exception执行了')
        print(exception)



class MyMiddleware2(MiddlewareMixin):
    def __init__(self, get_response):
        super(MyMiddleware2, self).__init__(get_response)
        print('MyMiddleware2 初始化执行')

    def process_request(self, request):
        print('MyMiddleware2 视图执行前执行一次')

    def process_response(self, request, response):
        print('MyMiddleware2 视图执行后执行一次')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MyMiddlware2 process_view执行了')

    def process_exception(self, request, exception):
        print('MyMiddleware2 process_exception执行了')
        print(exception)
# views.py

def test(request):
    print('test 视图函数执行')
    print(test)
    a = 1/0
    return HttpResponse("test HttpResponse 返回了。")

访问,http://127.0.0.1:8000/test/

运行结果

当process_exception返回HttpResponse时

# middlewares.py
class MyMiddleware1(MiddlewareMixin):
    def __init__(self, get_response):
        super(MyMiddleware1, self).__init__(get_response)
        print('MyMiddleware1 初始化执行')

    def process_request(self, request):
        print('MyMiddleware1 视图执行前执行一次')

    def process_response(self, request, response):
        print('MyMiddleware1 视图执行后执行一次')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MyMiddlware1 process_view执行了')

    def process_exception(self, request, exception):
        print('MyMiddleware1 process_exception执行了')
        print(exception)
        return HttpResponse(exception)



class MyMiddleware2(MiddlewareMixin):
    def __init__(self, get_response):
        super(MyMiddleware2, self).__init__(get_response)
        print('MyMiddleware2 初始化执行')

    def process_request(self, request):
        print('MyMiddleware2 视图执行前执行一次')

    def process_response(self, request, response):
        print('MyMiddleware2 视图执行后执行一次')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MyMiddlware2 process_view执行了')

    def process_exception(self, request, exception):
        print('MyMiddleware2 process_exception执行了')
        print(exception)
        return HttpResponse(exception)

访问,http://127.0.0.1:8000/test/

运行结果:


程序执行流程

  1. 客户端发出http请求到达中间件,执行中间件中的process_request方法
  2. 执行路由匹配
  3. 执行process_view方法
  4. 执行相应的视图函数
    1. (如果执行视图函数时出现运行错误)
    2. process_exception方法捕捉到异常就会执行
    3. 后续的process_exception方法就不会再执行了(如果上一个返回值不为None)
  5. 最后执行process_response方法
  6. 返回信息给客户端浏览器


process_template_response

process_template_response(request, response)

process_template_response函数是在视图函数执行完后立即执行的

process_template_response函数响应有一个前提条件,那就是视图函数返回的对象要有一个render方法(或者表明该对象是一个TemplateResponse对象或等价方法)

# middlewares.py
class MyMiddleware1(MiddlewareMixin):
    def __init__(self, get_response):
        super(MyMiddleware1, self).__init__(get_response)
        print('MyMiddleware1 初始化执行')

    def process_request(self, request):
        print('MyMiddleware1 视图执行前执行一次')

    def process_response(self, request, response):
        print('MyMiddleware1 视图执行后执行一次')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MyMiddlware1 process_view执行了')

    def process_exception(self, request, exception):
        print('MyMiddleware1 process_exception执行了')
        print(exception)

    def process_template_response(self, request, response):
        print("MyMiddleware1 process_template_response执行了")
        return response
# views.py
def test(request):
    return TemplateResponse(request, 'base.html')

执行结果:

如果要对返回的HttpResponse数据进行处理,可以把要处理的信息封装在一个类里,只要类里定义了render方法,process_template_response方法才会执行

class MyResponse:
    def __init__(self, response):
        self.response = response

    def render(self):
        return self.response


def index(request):
    response = HttpResponse("index page")
    return MyResponse(response)


  • 标签云

  • 支付宝扫码支持一下

  • 微信扫码支持一下



基于Nginx+Supervisord+uWSGI+Django1.11.1+Python3.6.5构建

版权所有 © 2020-2021 August Rush

京ICP备20007446号-1 & 豫公网安备 41100202000460号

网站地图 & RSS | Feed