当前位置: 首页 > news >正文

Django中间件middleware

本文讲述的内容基于 Django 1.11

摘要

Django 中的中间件(middleware),是一个镶嵌到Django的request/response处理机制中的一个hooks框架,是一个修改django全局输入输出的一个底层插件系统。让我们可以自定义想要的一些功能来处理用户的请求。

在Django中,中间件其实就是一个类,在类中包含一组特定的功能,在请求到来或者结束时,Django会根据我们定义的中间件规则执行中间件中对应的方法,一个 Django 项目默认激活的中间件在我们项目中的配置中可以看到是这个样子的:

  • settings.py
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',
]

MIDDLEWARE这里列表中的每一个元素,其实就是一个个单独的中间件,举例来说:django.middleware.csrf.CsrfViewMiddleware这个中间件,作用就是在我们的 form 表单提交请求的时候,提交的时候必须要带上csrf_token,否则就不会正确提交。

中间件使用也需要讲究顺序,下一层依赖上一层的封装,例如,我们的AuthenticationMiddleware是一个认证中间件,在session 中保存认证用户的信息,但是他必须依赖于SessionMiddleware才可以被正确使用,所以他也必须在SessionMiddleware之后。但是具体的顺序问题可以参考这里

中间件结构

中间件类中需要包含以下处理方法:

1. process_request(self, request)
2. process_view(self, request, callback, callback_args, callback_kwargs)
3. process_template_response(self, request, response)
4. process_exception(self, request, exception)
5. process_response(self, request, response)

执行过程

以我们的项目中默认中间件为例子,具体的流程如下所示:
1119052-20180312181939782-1073113364.png

中间件执行前提

中间件要按照一定的顺序一层一层的执行下去,需要按照标准返回特定的内容:

  • 如果为 None,则按照顺序继续向下执行
  • 如果为 HttpResonse 对象,则直接将这个对象返回给用户

此处有一个版本前后的区别,请大家注意区分

  • 在 Django1.10之后, 当某个中间件,例如CsrfViewMiddleware请求process_request没有返回 None 后,这个请求会交给CsrfViewMiddlewareprocess_response来返回,即返回给相同一层的中间件来返回:
    1119052-20180312181952384-1525067925.png

  • 在 Django1.10之前的版本,会返回到最底层的中间件来返回:
    1119052-20180312182002392-2354565.png

中间件方法:

  • process_request(self, request)
其中request参数就是我们的HttpRequest对象,process_request 会在每个request在被决定使用哪个view之前调用,它会返回None或HttpResponse对象
  • process_view(self, request, callback, callback_args, callback_kwargs)
其中request参数就是的HttpRequest对象,callback 就是请求被决定使用的 view 函数,书具体的函数名,不是字符串类型。callback_args和callback_kwargs是 view 函数需要接受的参数,它会返回None或HttpResponse对象
  • process_template_response(self, request, response)
其中request 是 HttpRequest 对象, response 是一个由Django view或者中间件返回的TemplateResponse 对象,process_template_response()在 view 使用 render 渲染一个模版对象完成之后被调用,它必须返回一个render 方法执行后的response对象。
  • process_exception(self, request, exception)
其中request参数就是的HttpRequest对象,exception是view函数中raise的Exception对象,当 view 函数 raise 一个 exception 的时候调用process_exception,它会返回None或HttpResponse对象
  • process_response(self, request, response)
其中request是 HttpRequest 对象,response 是一个django view或者中间件返回的 HttpResponse 或者StreamingHttpResponse对象,process_response会在所有响应到达浏览器之前被调用

中间件的详细执行流程

  • 由于process_template_response在特定的 rander 渲染中才会被调用,所以过程中不添加该方法
    1119052-20180312182014989-1613488089.png

自建中间件与执行过程测试

为了更加清晰的展示中间件的执行过程与如何自定义一个中间件,我们模拟一个简单的用户请求和中间件执行过程:

  • 自定义中间件
from django.utils.deprecation import MiddlewareMixin

class MyMiddleware_1(MiddlewareMixin):

    def process_request(self, request):
        print("自定义 process_request 1")
        return None

    def process_response(self, request, response):
        print("自定义 process_response 1")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("自定义 process_view 1")
        return None

    def process_exception(self, request, exception):
        print("自定义 process_exception 1")


class MyMiddleware_2(MiddlewareMixin):

    def process_request(self, request):
        print("自定义 process_request 2")
        return None

    def process_response(self, request, response):
        print("自定义 process_response 2")
        return response

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("自定义 process_view 2")
        return None

    def process_exception(self, request, exception):
        print("自定义 process_exception 2")
  • 引入
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',
    'app01.middle_by_me.MyMiddleware_1',  # 第一个自定义 middleware
    'app01.middle_by_me.MyMiddleware_2'  # 第二个自定义 middleware
]
  • 输出结果
    1119052-20180312182028479-1501572255.png

自定义中间件应用场景

应用场景这个问题其实不是很好去固定,因为大家在实际使用过程中的需求都不尽相同,所以我简单的举个我可以想到的例子吧。

在不修改业务逻辑源代码的情况下,我可以使用中间件来对用户的访问进行一定的筛选过滤,或者访问控制。还有能想到的更加牛逼的操作是当源站的 CDN,请求穿透源站,middleware 判断请求的内容是否在缓存中,如果在缓存直接返回,而可以不经过业务后端逻辑,是不是很骚~

是不是很像一个所有视图函数的装饰器~~

转载于:https://www.cnblogs.com/forsaken627/p/8550826.html

相关文章:

  • 结构图
  • libimobiledevice --Mingw32交叉编译
  • 在c:forEach作用域外使用标签所产生的值
  • 04-手机套餐:建造者模式
  • css总结1:position定位:absolute/relative/fixed
  • zzw原创_非root用户启动apache的问题解决(非root用户启动apache的1024以下端口)
  • SQL循环语句 详解
  • OpenCV问题集锦
  • 20154327 Exp1 PC平台逆向破解
  • ios 通知与通知传值2018.03.17
  • 20155307《网络对抗》PC平台逆向破解(二)
  • 273. Integer to English Words
  • DevOps是一种文化,不是角色!
  • 00004、python+selenium 的三种时间等待方式
  • SQL SERVER存储过程一
  • 网络传输文件的问题
  • Django 博客开发教程 8 - 博客文章详情页
  • docker python 配置
  • express如何解决request entity too large问题
  • HTTP--网络协议分层,http历史(二)
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Next.js之基础概念(二)
  • nginx 负载服务器优化
  • PHP 7 修改了什么呢 -- 2
  • PHP面试之三:MySQL数据库
  • sessionStorage和localStorage
  • XML已死 ?
  • 基于遗传算法的优化问题求解
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 力扣(LeetCode)22
  • 前端面试总结(at, md)
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 一些css基础学习笔记
  • linux 淘宝开源监控工具tsar
  • puppet连载22:define用法
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • #etcd#安装时出错
  • (C#)一个最简单的链表类
  • (LeetCode C++)盛最多水的容器
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)php新闻发布平台 毕业设计 141646
  • (九)c52学习之旅-定时器
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (转)Linux整合apache和tomcat构建Web服务器
  • .dwp和.webpart的区别
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .net framework 4.0中如何 输出 form 的name属性。
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .project文件
  • @TableLogic注解说明,以及对增删改查的影响
  • []sim300 GPRS数据收发程序
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [Android 13]Input系列--获取触摸窗口