88.Django中间件的说明与使用方法

news2024/11/14 19:20:51

1. 概述

​ AOP(Aspect Oriented Programming ),面向切面编程,是对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。可以实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

​ 面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP的功能将切面织入到主业务逻辑中。所谓交叉业务逻辑是指,通用的,与主业务逻辑无关的代码,如安全检查,事物,日志等。若不使用AOP,则会出现代码纠缠,即交叉业务逻辑与主业务逻辑混合在一起。这样,会使业务逻辑变得混杂不清。
举个例子:银行系统取款会有一个流程查询也会有一个流程。

在这里插入图片描述

​ Django的中间件,就是应用AOP技术来实现的,它是django请求/响应处理的钩子框架,是一个轻巧的低级“插件”系统,在不修改django项目原有代码的基础上,可以全局改变django的输入或输出,每个中间件组件负责执行某些特定功能。

​ PS:因为中间件改变的是全局(加入到整个流程),所以需要谨慎实用,滥用的话,会影响到服务器的性能。同样的,使用装饰器也可以达到这个效果,但是使用装饰器的话需要依次添加,代码会变得很复杂

2. django默认中间件

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

​ 一般情况下这些中间件都会启用(最少CommonMiddleware会启用)

3. 自定义中间件说明

如果需要增加自定义的中间件(该中间件类必须继承MiddlewareMixin(django.utils.deprecation)),一般是添加在系统的中间件之下,如:

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',
    
    # 自定义中间件
    'my_app.middleware.MyMiddleware',
]

中间件中主要有以下方法(一个中间件类最少需要实现下列方法中的一个):

  • process_request:处理请求对象,请求到达django框架时,第一时间调用

    多个中间件之间顺序调用

    参数:request

    返回:

    • response:调用当前中间件的process_response处理
    • None:调用下一个中间件的process_request处理
  • process_response:处理响应对象,视图函数返回response后,调用

    多个中间件之间倒序调用

    参数:request, response

    返回:

    • response:调用上一个中间件的process_response处理
  • process_view:视图预处理,在视图函数处理之前调用,即请求在urlconf当中匹配到对应的视图函数之后,先不调用视图函数,而是先调用此方法

    多个中间件之间顺序调用

    参数:request,view_func,view_args,view_kwargs

    ​ view_func:url路由匹配到的视图函数, 不是字符串,是函数对象

    ​ view_args:视图函数的可变参数

    ​ view_kwargs:视图函数的可变关键字参数

    返回:

    • response:调用最后一个中间件的process_response开始处理
    • None:调用下一个中间件的process_view处理
  • process_exception:在视图函数处理过程抛出异常时调用,中间件的方法(除了process_template_response)中抛出异常不会触发

    多个中间件之间倒序调用

    参数:request,exception

    ​ exception:是处理过程中抛出的异常对象

    返回:

    • response:之后的process_exception都不会触发,而是直接调用最后一个中间件的process_response处理
    • None:调用上一个中间件的process_exception处理
  • process_template_response:默认不执行,在视图函数完成操作后调用,除非视图函数返回的response中有render方法

    多个中间件之间倒序调用

    参数:request,response

    ​ response:不是HttpReponse,而是具有render方法的对象,譬如:SimpleTemplateResponse对象,在(django.template.response中)

    返回:

    • response:具有render方法的对象,继续调用上一个中间件的process_template_response处理,最后一个process_template_response处理完成后,会自动调用 response对象中的render方法,得到一个HttpResponse对象,进行返回,再调用process_response操作
    中间件方法的执行时有顺序的,process_request与process_view是按照顺序去执行的,而process_response、process_exception和process_template_response是反序的 :
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-io9SmTjf-1669197395429)(.\imgs\image-20210729085034649.png)]

​ 总结:用户请求 >> process_request >> urlconf路由匹配,找到对应的视图函数 >> process_view >> 视图函数 >> process_template_response(如果视图函数返回的response,有render方法,否则这一步不会执行) >> process_response >> 返回response到用户

​ 其中,在 视图函数 和 process_template_response 处理过程中,如果出现 exception ,那么就会倒序执行 中间件的process_exception

3.1 中间件调用顺序测试process_request

结果:
先执行中间件,按照settings配置顺序执行,然后再执行视图函数
urls

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('middleware_app.urls'))
]

views

from django.shortcuts import render,HttpResponse

# Create your views here.
def middleware_test(request):
    print('调用了视图函数')
    return HttpResponse('测试中间件成功')

中间件

from django.utils.deprecation import MiddlewareMixin
class FirstMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('FirstMiddleware process_request')

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

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

settings

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_app.middlewaretest.FirstMiddleware',
    'middleware_app.middlewaretest.SecondMiddleware',
    'middleware_app.middlewaretest.ThirdMiddleware',

]

3.2 中间件调用顺序测试process_response

**结果: **
当request存在返回时。
返回顺序,先执行First然后,执行Second的request,然后渲染模板,最后从2执行到1的response。不执行3。
因为如果request存在返回时,执行完return就直接执行response,response又是倒叙执行,就跳过了3

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse
class FirstMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('FirstMiddleware process_request')
    def process_response(self,request,response):
        print('FirstMiddleware process_response')
        return response


class SecondMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('SecondMiddleware process_request')
        return HttpResponse('return SecondMiddleware')
    def process_response(self,request,response):
        print('SecondMiddleware process_response')
        return response


class ThirdMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('ThirdMiddleware process_request')
    def process_response(self,request,response):
        print('ThirdMiddleware process_response')
        return response

3.3 中间件调用顺序测试process_view

结果
如果不存在返回的话,就先执行request、view,再执行函数视图,再倒叙执行response。
如果存在返回的话,就先执行request,再顺序执行到存在返回的视图(不执行之后的),最后倒叙执行response。不执行函数视图了。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse
class FirstMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('FirstMiddleware process_request')
    def process_response(self,request,response):
        print('FirstMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('FirstMiddleware process_view')


class SecondMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('SecondMiddleware process_request')
        # return HttpResponse('return SecondMiddleware')
    def process_response(self,request,response):
        print('SecondMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('SecondMiddleware process_view')
        return HttpResponse('return SecondMiddleware')

class ThirdMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('ThirdMiddleware process_request')
    def process_response(self,request,response):
        print('ThirdMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('ThirdMiddleware process_view')

3.4 中间件调用顺序测试process_exception

结果
先将视图函数view中添加抛出异常代码。若exception无返回时,就按顺序执行request,顺序执行view。再倒叙执行exception。执行完views视图函数之后,倒叙执行response;
就按顺序执行request,顺序执行view。再倒叙执行exception,但是执行到返回函数就不会继续倒叙执行了。执行完views视图函数之后(但不会执行函数中raise抛出的异常),倒叙执行response。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse
class FirstMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('FirstMiddleware process_request')
    def process_response(self,request,response):
        print('FirstMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('FirstMiddleware process_view')
    def process_exception(self, request, exception):
        print('FirstMiddleware process_exception')


class SecondMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('SecondMiddleware process_request')
        # return HttpResponse('return SecondMiddleware')
    def process_response(self,request,response):
        print('SecondMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('SecondMiddleware process_view')
        # return HttpResponse('return SecondMiddleware')
    def process_exception(self, request, exception):
        print('SecondMiddleware process_exception')
        return HttpResponse('return SecondMiddleware')


class ThirdMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('ThirdMiddleware process_request')
    def process_response(self,request,response):
        print('ThirdMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('ThirdMiddleware process_view')
    def process_exception(self, request, exception):
        print('ThirdMiddleware process_exception')
from django.shortcuts import render,HttpResponse

# Create your views here.
def middleware_test(request):
    print('调用了视图函数')
    raise Exception('中间件抛出异常')
    return HttpResponse('测试中间件成功')

3.5 中间件测试调用顺序process_template_response

结果
若视图函数中不存在render,就不会触发process_template_response函数;若存在,在调用完视图后倒叙执行。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse
class FirstMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('FirstMiddleware process_request')
    def process_response(self,request,response):
        print('FirstMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('FirstMiddleware process_view')
    def process_exception(self, request, exception):
        print('FirstMiddleware process_exception')
    def process_template_response(self,request, response):
        print('FirstMiddleware process_template_response')
        return response


class SecondMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('SecondMiddleware process_request')
        # return HttpResponse('return SecondMiddleware')
    def process_response(self,request,response):
        print('SecondMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('SecondMiddleware process_view')
        # return HttpResponse('return SecondMiddleware')
    def process_exception(self, request, exception):
        print('SecondMiddleware process_exception')
        return HttpResponse('return SecondMiddleware')
    def process_template_response(self,request, response):
        print('SecondMiddleware process_template_response')
        return response


class ThirdMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('ThirdMiddleware process_request')
    def process_response(self,request,response):
        print('ThirdMiddleware process_response')
        return response
    def process_view(self,request,view_func,view_args,view_kwargs):
        print('ThirdMiddleware process_view')
    def process_exception(self, request, exception):
        print('ThirdMiddleware process_exception')
    def process_template_response(self,request, response):
        print('ThirdMiddleware process_template_response')
        return response

4. 常见自定义中间件功能

总之,你如果有对全局request或response的操作需求,那么就可以使用中间件,譬如:

  1. IP过滤:对一些特定IP地址返回特定响应
  2. URL过滤:如果用户访问的是login视图,则通过;如果访问其他视图,需要检测是不是有session已经有了就通过,没有就返回login页面。这样就不用在多个视图函数上写装饰器login_required
  3. 内容压缩:response内容实现gzip的压缩,返回压缩后的内容给前端
  4. CDN:内容分发网络,实现缓存,如果缓存中有数据直接返回,没有找到缓存再去请求视图
  5. URL过滤:某个子应用升级暂停使用,某个特定的path路径下的请求,返回一个特定页面

5. 使用中间件——示例URL过滤

如何使用Django中间件实现访问某一些网页进行跳转到指定URL的地址(登录,系统维护)
url

from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
    path('middleware_test/',views.middleware_test),
    path('middleware_url/', views.middleware_url)
]

views

from django.shortcuts import render,HttpResponse
from django.template.response import SimpleTemplateResponse
def middleware_url(request):
    return HttpResponse('系统功能升级中') # 不会访问到他

中间件views

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,HttpResponse
from django.shortcuts import render
class URLMiddleware(MiddlewareMixin):
    def process_request(self,request):
        if request.path.startswith('/middleware_url/'):
            return render(request,'middleware_app/middleware_url.html')

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    系统在升级啊啊啊
</body>
</html>

settings配置

MIDDLEWARE = [
    # 最先触发
    'middleware_app.middlewaretest.URLMiddleware',

    '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_app.middlewaretest.FirstMiddleware',
    'middleware_app.middlewaretest.SecondMiddleware',
    'middleware_app.middlewaretest.ThirdMiddleware',

]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

css-实现卡牌的发牌和翻牌动画

场景描述&#xff1a; 打开抽卡界面&#xff0c;卡牌出现并发牌至固定的位置&#xff0c;此时展示的是卡牌的背面&#xff1b;用户点击卡牌时&#xff0c;卡牌进行翻转&#xff0c;并展示卡牌内容&#xff0c;或者发牌后自动进行翻转和展示。 本实例在页面挂载后自动播放动画&…

前端网站动态主题色解决方案

动态主题色替换分两种&#xff1a;UI 组件库主题色替换和系统主题色替换。 组件库 UI 动态主题替换现阶段只在 Element-UI 和 Vant-UI 测试过&#xff0c;根据排查这种方案应该适用于所有类似的动态主题色替换场景。 1. UI 组件库主题色替换 在进入到这一部分之前&#xff0c;…

力扣232 - 用栈实现队列【C语言实现】

用栈实现队列~一、题目描述二、思路分析三、代码详解1、结构声明与展开剖析2、入队【入栈思想】3、获取队头【出栈思想】4、出队【复用思想】5、逐步算法图解四、整体代码展示&#x1f4bb;C语言代码实现五、总结与提炼一、题目描述 示例 1&#xff1a; 输入&#xff1a; [“My…

Java基础知识+必考面试题(分享收藏版)

在学习Java语言之前&#xff0c;我们要了解相关知识体系&#xff0c;才能更好的掌握学习。那么下面我们就一起来学习JAVA语言吧~ Java语言概述 Java语言是Sun公司在1995年推出的高级编程语言&#xff0c;编程语言就是计算机语言&#xff0c;人们可以通过使用编程语言让计算机完…

Webfunny 创始人:Skywalking × Zabbix 与观纵探索可观测性

作为 Webfunny 的 PMC&#xff0c;应伟长期致力于前端监控、埋点探针的产品研发&#xff0c;伴随着全链路监控的探索&#xff0c;在整合 Skywalking 与 Zabbix 打造一体化监控平台的实践中&#xff0c;是怎样的心路历程&#xff1f; “ 从前端监控到全链路监控的挑战 Webfun…

Mockplus Cloud updated传达设计意图的新方法

Mockplus Cloud updated传达设计意图的新方法 增加了Mockplus Cloud UI 2.0&#xff0c;使UI更加直观和简洁。 引入了注解&#xff0c;为向开发人员传达设计意图提供了一种新的方式。 添加了上传图像以进一步解释任务注释的功能。 优化任务创建以改善用户体验。 提高了下载、导…

BUUCTF·鸡藕椒盐味·WP

来源&#xff1a;https://buuoj.cn/challenges#%E9%B8%A1%E8%97%95%E6%A4%92%E7%9B%90%E5%91%B3 分析 鸡藕椒盐味奇偶校验位 ~验证码如下&#xff1a;1100 1010 0000 ,而且打印的时候倒了一下。把答案哈希一下就可以提交了~ 验证码是二进制数&#xff0c;但是题目也提示了这…

【Linux】了解系统整体状态-top命令

Top命令 查看系统整体状态&#xff0c;只能查看当前系统的大概情况 整个机器CPU 内存使用情况 IO使用情况 CPU(s)&#xff1a;0.0% CPU使用情况 %us&#xff1a;user CPU time 用户占用CPU百分比 %sy&#xff1a;system CPU time 内核空间占用CPU百分比 %ni&#x…

Node的web编程(三)

一、jQuery中对ajax封装 1、底层封装&#xff1a;封装了XMLHttpRequest对象&#xff0c;既可以发送get请求&#xff0c;也可以发送post请求 $.ajax({ url&#xff1a;服务器地址, type&#xff1a;请求方式, data&#xff1a;{ //客户端向服务器发送的请求数据 参数名1&#x…

SolidWorks弯曲的波纹管制作教程

如何使用SolidWorks制作波纹管呢?可能很多小伙伴都会做,那完全的波纹管如何制作呢?有的小伙伴可能不止一种方法,可能有很多方法,可以用扫描路径等,下面我用其他方法去实现下面效果图 首先新建一个零件,选前视基准面,画一个40MM的圆,如下图 然后用拉伸凸台命令,长度给…

.net----结构和枚举

结构和枚举结构结构的声明和调用声明调用结构&#xff1a;结构的成员枚举枚举的使用枚举&#xff1a;Flags枚举结构 轻量级的类&#xff0c;与类很相似&#xff0c;均为包含数据成员和函数成员的数据结构 结构与类的区别 结构是值类型且被称为具有值语义&#xff1b;而类是引…

【Lilishop商城】No2-2.确定软件架构搭建一(本篇包括MVC框架、持久框架、缓存、认证工具、安全框架等)

仅涉及后端&#xff0c;全部目录看顶部专栏&#xff0c;代码、文档、接口路径在&#xff1a; 【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 上一篇已经看了项目的开发架构&#xff0c;都需要哪些技术&#xff0c;都按照哪些规范&#xff0c;都哪…

免杀Backdoor-factory

Patch ● 通过替换EXE、DLL、注册表等方法修复系统漏洞或问题的方法 ● BDF&#xff1a;向二进制文件中增加或者删除代码内容 ○ 某些受保护的二进制程序无法patch ○ 存在一定概率文件会被patch坏掉 后门工厂 ● 适用于windows PE x32/x64和Linux ELF x32/x64(OSX) ● 支持…

【JVM】内存模型:原子性、可见性、有序性的问题引出与解决

一、内存模型 很多人将【java 内存结构】与【java 内存模型】傻傻分不清&#xff0c;【java 内存模型】是 Java MemoryModel&#xff08;JMM&#xff09;的意思。 简单的说&#xff0c;JMM 定义了一套在多线程读写共享数据时&#xff08;成员变量、数组&#xff09;时&#x…

(七)RabbitMQ持久化

RabbitMQ持久化1、概念2、队列持久化3、消息持久化4、不公平分发5、预取值1、概念 默认情况下 RabbitMQ 退出或由于某种原因崩溃时&#xff0c;它忽视队列和消息&#xff0c;除非告知它不要这样做。确保消息不会丢失需要做两件事&#xff1a;我们需要将队列和消息都标记为持久化…

广义OOD检测最新综述

arXiv在2021年10月21日上传的论文**“Generalized Out-of-Distribution Detection: A Survey“&#xff0c;作者来自新加坡的南洋理工大学&#xff08;NTU&#xff09;和美国的威斯康星大学Madison分校**。 OOD检测对确保机器学习系统的可靠性和安全性至关重要&#xff0c;例如…

秦皇岛科学选育新品种 国稻种芯·中国水稻节:河北谱丰收曲

秦皇岛科学选育新品种 国稻种芯中国水稻节&#xff1a;河北谱丰收曲 冀时客户端报道&#xff08;河北台 张志刚 米弘钊 赵永鑫&#xff09; 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 国稻种芯中国水稻节 中国农民丰收节国际贸易促进会 中国三农智库网-功能性农业农业…

Java对象拷贝原理剖析及最佳实践

作者&#xff1a;宁海翔 1 前言 对象拷贝&#xff0c;是我们在开发过程中&#xff0c;绕不开的过程&#xff0c;既存在于Po、Dto、Do、Vo各个表现层数据的转换&#xff0c;也存在于系统交互如序列化、反序列化。 Java对象拷贝分为深拷贝和浅拷贝&#xff0c;目前常用的属性拷…

2023年系统规划与设计管理师-学习计划安排

一.学习计划和安排&#xff1a; 序号 学习内容 分数以及题型 学习安排 完成日期 1 浏览教程&#xff0c; 了解知识结构 1天 11/24 2 前三章内容&#xff1a; 课本&#xff0c; 单元练习&#xff0c; 思维导图&#xff0c; 总结归纳&#xff0c; 第一遍背诵 分数占…

希望所有计算机学生都知道这些宝藏课程

数据结构 青岛大学——王卓老师的数据结构与算法基础 浙江大学——陈越、何钦铭老师的数据结构课程 清华大学——邓俊辉老师的数据结构课程 北京大学——数据结构基础课程 操作系统 哈工大——李治军老师的操作系统 清华大学——操作系统原理 南京大学——操作系统概述 计算…