13.Django之中间件

中间键的介绍

    中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能

   如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现

   你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现

中间键就在Django项目的Setting.py文件中,Django自带的一些中间件

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',
]

Django的生命周期

自定义中间件

中间件可以定义为五个方法

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

在request阶段按顺序从上到下穿过,而在response则反过来

自定义一个中间件

在自定义一个中间件,就要自己写一个类,但必须继承MiddlewareMixin函数

在项目下创建一个utils的包全局的

然后创建一个py文件名字随便 如middlewares.py

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


class MD1(MiddlewareMixin):
    def process_request(self,request):
        print('MD1的process_request')

    def process_response(self,request,response): #request和response两个参数必须有
        print('MD1的Process_response')
        # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容
        return response
        # return HttpResponse('ok')

class MD2(MiddlewareMixin):
    def process_request(self,request):
        print('MD2的process_request')

    def process_response(self,request,response):
        print('MD2的Process_response')
        return response
        # return HttpResponse('ok')

settings.py的MIDDLEWARE配置项中注册两个自定义中间件

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',
    'utils.middlewares.MD1', #自定义中间件MD1,写的是路径
    'utils.middlewares.MD2', #自定义中间件MD2
]

打印的结果

Process_request

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

以上返回的值是None,则继续按照django定义的规则继续执行,如果是HttpResponse对象,则直接将该对象返回给用户

Process_response

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

如果把自定义中间件的位置调换就会出现一下结果

流程图

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方法。

给DM1和DM2添加process_view

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


class MD1(MiddlewareMixin):
    def process_request(self, request):
        print('MD1的process_request')

    def process_response(self, request, response):  # request和response两个参数必须有
        print('MD1的Process_response')
        # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容
        return response
        # return HttpResponse('ok')
    def process_view(selfself,request,view_func,view_args,view_kwargs):
        print('MD1的process_view')
        print(view_func,view_func.__name__)


class MD2(MiddlewareMixin):
    def process_request(self, request):
        print('MD2的process_request')

    def process_response(self, request, response):
        print('MD2的Process_response')
        return response
        # return HttpResponse('ok')
    def process_view(selfself,request,view_func,view_args,view_kwargs):
        print('MD2的process_view')
        print(view_func,view_func.__name__)

返回结果

如果在MD1的process_view添加一个return HttpResponse('ok')返回的结果

执行的流程图

process_exception

process_exception(self,request,exception)

  两个参数

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

 只有在视图函数中出现异常才会执行

给DM1和DM2添加process_exception

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


class MD1(MiddlewareMixin):
    def process_request(self, request):
        print('MD1的process_request')

    def process_response(self, request, response):  # request和response两个参数必须有
        print('MD1的Process_response')
        # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容
        return response
        # return HttpResponse('ok')
    def process_view(selfself,request,view_func,view_args,view_kwargs):
        print('MD1的process_view')
        print(view_func,view_func.__name__)
        # return HttpResponse('ok')

    def process_exception(self,request,exception):
        print(exception)
        print("MD1的process_exception")



class MD2(MiddlewareMixin):
    def process_request(self, request):
        print('MD2的process_request')

    def process_response(self, request, response):
        print('MD2的Process_response')
        return response
        # return HttpResponse('ok')
    def process_view(selfself,request,view_func,view_args,view_kwargs):
        print('MD2的process_view')
        print(view_func,view_func.__name__)

    def process_exception(self,request,exception):
        print(exception)
        print("MD2的process_exception")
        

在login'页面添加个异常

raise ValueError()

运行结果

后面还有

MD2的Process_response
MD1的Process_response

 

如果在MD2中的Process_exception下加

return HttpResponse('ok')

运行结果为

流程图

process_template_response(很少用)

process_template_response(self,request,response)

它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)

process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)

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


class MD1(MiddlewareMixin):
    def process_request(self, request):
        print('MD1的process_request')

    def process_response(self, request, response):  # request和response两个参数必须有
        print('MD1的Process_response')
        # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容
        return response
        # return HttpResponse('ok')
    def process_view(selfself,request,view_func,view_args,view_kwargs):
        print('MD1的process_view')
        print(view_func,view_func.__name__)
        # return HttpResponse('ok')

    def process_exception(self,request,exception):
        print(exception)
        print("MD1的process_exception")

    def process_template_response(self,request,response):
        print("MD1的process_template_response")
        return response



class MD2(MiddlewareMixin):
    def process_request(self, request):
        print('MD2的process_request')

    def process_response(self, request, response):
        print('MD2的Process_response')
        return response
        # return HttpResponse('ok')
    def process_view(selfself,request,view_func,view_args,view_kwargs):
        print('MD2的process_view')
        print(view_func,view_func.__name__)

    def process_exception(self,request,exception):
        print(exception)
        print("MD2的process_exception")

    def process_template_response(self,request,response):
        print("MD2的process_template_response")
        return response

 views.py

def index(request):
    def render():
        print("in index/render")
        return HttpResponse("O98K")

    rep = HttpResponse("OK")
    rep.render = render
    return rep

运行结果

视图函数执行完之后,立即执行了中间件的process_template_response方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法

 Django请求流程

 

posted @ 2019-03-08 16:15  等待の喵  阅读(196)  评论(0编辑  收藏  举报