zoukankan      html  css  js  c++  java
  • Django 详解 中间件Middleware

    Django中间件

    还是涉及到django的请求生命周期。middle ware 请求穿过中间件到达url,再经过中间件返回给用户。

    简单实例

    django项目根目录新建一个Middle文件夹,再新建一个test.py文件

    在test文件中写入;其中的类必须继承 from django.utils.deprecation import MiddlewareMixin

    from django.utils.deprecation import MiddlewareMixin
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('m1')
        def process_response(self, request, response):
            print('m1_r')
            return response
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('m2')
        def process_response(self, request, response):
            print('m2_r')
            return response
    
    
    class M3(MiddlewareMixin):
        def process_request(self, request):
            print('m3')
    
        def process_response(self, request, response):
            print('m3_r')
            return response

    将你的测试中间件加入Django的中间件配置中,settings文件

    随便建一组对应路由。

    在index函数里面写上

    def index(request):
        print('到达')
        return HttpResponse('ok')

    查看结果:

    此时如果给某个中间件的process_request返回一个HttpResponse:

    #!/user/bin/env python
    # -*-coding: utf-8-*-
    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    class M1(MiddlewareMixin):
        def process_request(self, request):
            print('m1')
        def process_response(self, request, response):
            print('m1_r')
            return response
    
    
    class M2(MiddlewareMixin):
        def process_request(self, request):
            print('m2')
            return HttpResponse('中断')  # 这里返回
        def process_response(self, request, response):
            print('m2_r')
            return response
    
    
    class M3(MiddlewareMixin):
        def process_request(self, request):
            print('m3')
    
        def process_response(self, request, response):
            print('m3_r')
            return response
    

    查看下结果

    可能你好像懂了,但是并没有,真正的中间件过程其实还有一个process_view.

    View Code

    自定制中间件的另一种方式

    下面是最新的django2.1文档内的自定制中间件的另一种写法。

    一个中间件工厂是可以被调用的,它接收一个可调用的get_response方法并返回一个中间件。中间件也是可调用的,它接收请求并返回响应,就像一个view视图

    def simple_middleware(get_response):
        # 一次性配置和初始化
    
        def middleware(request):
            # 在每个请求之前被执行的代码
            #这个视图(和后面的中间件)被调用
    
            response = get_response(request)
    
            # 在每个请求或者响应之后代码被执行
            # the view is called.
    
            return response
    
        return middleware

    或者他也可以被重写成一个实例可以被调用的类,像这个:

    class SimpleMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
            # 一次性配置和初始化
    
        def __call__(self, request):
            # 在每一次请求之前代码被执行
            # 视图或者接下来的中间件被调用
            response = self.get_response(request)
    
            # 在每个请求或者响应之后代码将会被执行
            # the view is called.
    
            return response

    可调用的get_response是由django提供的,可以是真实的视图函数或者也可以是链上的下一个中间件。当前的中间件不需要具体精确地知道或者关心它是什么,只是它代表接下来执行(到来的)是什么。

    上面是一个小小的简化,可调用的get_response如果在中间件的最后一位,将不会是一个真实的视图函数,更可能是处理的一个外部包装方法,它关注于应用视图中间件,调用视图和合适的URL参数,并且使用template和exception中间件.

    中间件可以生存在你的Python路径的任何地方。

    __init__(get_response)

    中间件工厂必须接收一个get_response参数,你也可以为中间件初始化一些全局的状态。记住下面的这几点

    1、django只能使用get_response参数来初始化你的中间件,所以你不能定义__init__()来需要其他的参数

    2、跟__call__()方法每次请求被调用不同,__init__()方法只会被调用一次,当web服务启动的时候

    例如

    class LoginMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        @method_decorator(adminlogin)
        def __call__(self, request):
            if request.method == "PUT":
                request.data = dict(urllib.parse.parse_qsl(request.body.decode()))
                request.data.update(request.GET.dict())
            elif request.method == "POST":
                request.data = request.POST.copy().dict()
            response = self.get_response(request)
            return response
     1 def performance(func):
     2     def wrapper(request):
     3         mark1 = time.time()
     4         start = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(mark1))  # 2018-09-28 03:42:08
     5         response = func(request)
     6         if response.status_code == 200 and request.path.split('/')[1] == 'api':  # api url& response success
     7             mark2 = time.time()
     8             cost = mark2 - mark1
     9             end = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(mark2))
    10             note = 'url: %s |%s | total cost: %s | start time: %s | end time: %s
    ' % (request.path, request.GET, cost, start, end)
    11 
    12             with open(performance_file, 'a+') as obj:
    13                 obj.write(note)
    14         return response
    15     return wrapper
    16 
    17 
    18 class PerformanceMiddleware:
    19     def __init__(self, get_response):
    20         self.get_response = get_response
    21 
    22     @method_decorator(performance)
    23     def __call__(self, request):
    24         response = self.get_response(request)
    25         return response
    View Code

    详情请查阅django(version2.1)文档:https://docs.djangoproject.com/en/2.1/topics/http/middleware/

  • 相关阅读:
    Jquery easyui中的有效性检查
    当执行批量删除时
    nested exception is com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1044 > 1024
    java的四种取整方法
    springmvc乱码解决
    跨域
    垂直居中
    js判断数组
    安装 node-sass 的正确姿势
    js判断qq浏览器
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/9577840.html
Copyright © 2011-2022 走看看