• 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两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

  • 相关阅读:
    【HDOJ6666】Quailty and CCPC(模拟)
    【2019 Multi-University Training Contest 8】
    分布式锁的理解
    反射工具类【ReflectionUtils】
    Maven常用命令
    maven常用命令介绍
    mysql 优化策略(如何利用好索引)
    centos7搭建svn服务器及客户端设置
    Centos7 配置subversion
    Centos7更改网卡名称Eth0
  • 原文地址:https://www.cnblogs.com/ykgo/p/9392111.html
Copyright © 2020-2023  润新知