django—中间件

中间件

Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。每个中间件都可以完成特定的功能。

中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性,其它的MVC框架也有这个功能,名称为IoC

中间件在哪里?

在settings.py 我们可以看到:

这些字符串,就是一个一个的类。它们就是中间件。

中间件的方法

中间件可以定义五个方法,分别是:(主要的是process_request和process_response)

  • process_request(self,request)
  • process_view(self, request, view_func, view_args, view_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。

五个方法

1.处理请求前:在每个请求上,request对象产生之后,url匹配之前调用,返回None或HttpResponse对象。

def process_request(self,request):

  pass

2.处理视图前:在在每个请求上,url匹配之后,视图函数调用之前调用,返回None或HttpResponse对象。

def process_view(self, request, view_func, view_args, view_kwargs):

  pass

3.处理响应后:视图函数调用之后,所有响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse对象。

def process_response(self, request, response):

  pass

4.处理异常:只有当视图抛出异常时调用,在每个请求上调用,返回一个HttpResponse对象。

def process_exception(self, request, exception):

  pass

5.视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。

def process_response(self, request, response):

  pass

process_request

process_request有一个参数,就是request,这个request和视图函数中的request是一样的。

它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。

from django.utils.deprecation import MiddlewareMixin


class MyMiddle(MiddlewareMixin):
    def process_request(self, request):
        print("这是我的第一个中间件-----request----")


class MyMiddle2(MiddlewareMixin):

    def process_request(self, request):
        print("这是我的第二个中间件-----request----")
        return

 去settings.py注册

结果:

这是我的第一个中间件-----request----
这是我的第二个中间件-----request----

注意:

1  顺序是按中间件注册的顺序执行的。

2 不同中间件之间传递的request都是同一个对象

process_response

它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象

from django.utils.deprecation import MiddlewareMixin


class MyMiddle(MiddlewareMixin):
    def process_request(self, request):
        print("这是我的第一个中间件-----request----")

    def process_response(self, request, response):
        print("这是我的第一个中间件-----response----")
        return response      #  必须返回的是HttpResponse对象


class MyMiddle2(MiddlewareMixin):

    def process_request(self, request):
        print("这是我的第二个中间件-----request----")
        return

    def process_response(self, request, response):
        print("这是我的第二个中间件-----response----")
        return response

结果:

这是我的第一个中间件-----request----
这是我的第二个中间件-----request----
这是视图函数------view-------
这是我的第二个中间件-----response----
这是我的第一个中间件-----response----

我们可以看到

(1)它是在执行视图函数之后

(2)注意它的执行顺序:倒序执行。也就是与注册中间件的顺序相反。

process_view

process_view(self, request, view_func, view_args, view_kwargs)

该方法有四个参数

request是HttpRequest对象。

view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)

view_args是将传递给视图的位置参数的列表.

view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。

Django会在调用视图函数之前调用process_view方法。

它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。

如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。

from django.utils.deprecation import MiddlewareMixin


class MyMiddle(MiddlewareMixin):
    def process_request(self, request):
        print("这是我的第一个中间件-----request----")

    def process_response(self, request, response):
        print("这是我的第一个中间件-----response----")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        """
        :param request:  浏览器发来的请求对象
        :param view_func: 将要执行的视图函数的名字
        :param view_args: 将要执行的视图函数的位置参数
        :param view_kwargs: 将要执行的视图函数的关键字参数
        :return:
        """
        print("这是我的第一个中间件----process_view-----")
        print(view_func)


class MyMiddle2(MiddlewareMixin):

    def process_request(self, request):
        print("这是我的第二个中间件-----request----")
        return

    def process_response(self, request, response):
        print("这是我的第二个中间件-----response----")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是我的第二个中间件----process_view-----")
        print(view_func)

结果:

这是我的第一个中间件-----request----
这是我的第二个中间件-----request----
这是我的第一个中间件----process_view-----
<function index at 0x000001B7CF806BF8>
这是我的第二个中间件----process_view-----
<function index at 0x000001B7CF806BF8>
这是视图函数------view-------
这是我的第二个中间件-----response----
这是我的第一个中间件-----response----

我们可以看到:

(1)它的执行顺序与注册中间件的顺序一致,从上到下。

(2)在执行视图函数之前

process_exception

process_exception(self, request, exception)

该方法两个参数:

一个HttpRequest对象

一个exception是视图函数异常产生的Exception对象。

这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,

并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行

from django.utils.deprecation import MiddlewareMixin


class MyMiddle(MiddlewareMixin):
    def process_request(self, request):
        print("这是我的第一个中间件-----request----")

    def process_response(self, request, response):
        print("这是我的第一个中间件-----response----")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是我的第一个中间件----process_view-----")
        print(view_func)

    # 只有视图函数异常才会执行
    def process_exception(self, request, exception):
        print(exception)
        print("第一个中间件 中的process_exception")


class MyMiddle2(MiddlewareMixin):

    def process_request(self, request):
        print("这是我的第二个中间件-----request----")
        return

    def process_response(self, request, response):
        print("这是我的第二个中间件-----response----")
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print("这是我的第二个中间件----process_view-----")
        print(view_func)

    def process_exception(self, request, exception):
        print(exception)
        print("第二个中间件 中的process_exception")

结果:

这是我的第一个中间件-----request----
Traceback (most recent call last):
这是我的第二个中间件-----request----
这是我的第一个中间件----process_view-----
<function index at 0x000001BEB3206BF8>
这是我的第二个中间件----process_view-----
<function index at 0x000001BEB3206BF8>
这是视图函数------view-------
----------------------------------------------
第二个中间件 中的process_exception
第一个中间件 中的process_exception
----------------------------------------------
这是我的第二个中间件-----response----
这是我的第一个中间件-----response----

可以看到:

(1)执行顺序是倒序

(2)在执行视图函数之后,返回响应之前

中间的执行过程

请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的process_response方法,将HttpResponse对象返回给浏览器。也就是说:如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法。

process_request方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。加入中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。

process_template_response和process_exception两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

原文地址:https://www.cnblogs.com/ykgo/p/9392111.html