## django中间件 ## 内容概要 django中间件简介 django中间件两个重要方法 django自定义中间件 django中间件三个了解方法 基于django中间件实现功能的插拔式设计 ## 内容详细 django默认有七个中间件 并且还支持用户自定义中间件 中间件主要可以用于:用户访问频率的校验 用户权限的校验等全局型功能需求 ```python 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', ] ```  ## 自定义中间件 1.创建存储自定义中间件代码的py文件或目录(如果中间件很多) 2.产靠自带中间件的代码编写类并继承 3.在类中编写五个可以自定义的方法 4.一定要在配置文件注册中间件才可以生效 ```python 中间件可以定义五个方法,分别是:(主要的是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) ``` ### 需要掌握的两种方法 #### process_request 1. 请求来的时候从上往下依次经过每一个注册了中间件里面的该方法 如果没有则直接跳过 2. 如果该方法自己返回了HttpResponse对象那么不在往后执行而是直接原路返回 #### process_response 1. 响应走的时候从下往上依次经过每一个注册了的中间件里面的方法 如果没有则直接跳过 2. 该方法有两个request和response形参response指代的就是后端想要返回给前端浏览器的数据 该方法必须返回该形参 也可以替换 如果在执行process_request方法的时候直接返回了HttpResponse对象那么会原路返回执行process_response不是执行所有 ### 需要了解的 process_view process_exception process_template_response ## 自定义中间件实操 ```python from django.utils.deprecation import MiddlewareMixin class Mymiddle01(MiddlewareMixin): def process_request(self, request): print('from mymiddleware01 request') def process_response(self,request,response): return response class Mymiddle02(MiddlewareMixin): def process_request(self,request): print('from mymiddleware02 request') def process_response(self,request,response): return response ```  ### process_request  ### process_response  ### 如果在某一个中间件中直接返回了HTTP Response对象那么就不会在向下执行直接从当前中间件向上原路返回  ### 那么也可以达成狸猫换太子的效果  ### 结合生命周期流程图   ## django中间件的三个了解的方法 ### 1.process_view 路由匹配成功之后执行的视图函数/类之前自动触发(顺序同process_request) ```python from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Mymiddle01(MiddlewareMixin): def process_request(self, request): print('from mymiddleware01 request') def process_response(self, request, response): print('from mymiddleware01 response') return response def process_view(self, request, view_func, view_args, view_kwargs): print('from mymiddleware01 view') ```  ### 2.process_exception 视图函数/视图类执行报错自定触发(顺序同process_response) ```python def process_exception(self,request,exception): print('from mymiddleware01 exception') ```  ### 3.process_template_response 视图函数/视图类返回的HttpResponse对象含有redner并且对应一个方法的时候自动触发(顺序同process_response) 一定要把接收的HttpResponse对象返回出去 ```python def process_template_response(self,request,response): print('from mymiddleware01 template_response') return response ```  ## 基于django中间件实现的插拔式设计 将各个功能制作成配置文件的字符串形式 如果想拥有该功能就编写对应的字符串 如果不想拥有则注释掉对应的字符串 ### 补充知识 如果想用字符串导入模块 ```python import importlib s1 = 'bbb.b' # aaa.bbb.ccc.b res = importlib.import_module(s1) # from aaa.bbb.ccc import b print(res) # ``` 注意字符串的结尾最小单位只能是py文件 不能是py文件里面的变量名 Django的settings文件里好多都是字符串 但是呢都是不简单的字符串 每一个字符串对应着一个py文件就代表着一个特定的功能 如果你想这个字符串有这个功能就加上 不想用就直接注释点 那么如何利用字符串导模块? 在纯python情况下  利用字符串导模块 内置模块importlib  如图:  按照点号从右开始切割一个 它的底层还是按照from导模块的句式  局限性这个模块的最小单位是py文件名 不能到py文件里的变量名  需求分析: 模拟编写一个消息通知功能(微信、qq、邮箱) 通过点击一个按钮就能触发消息 ### 方式1:简单版 基于函数封装 ```python def send_qq(content): print('从qq发送消息:'+str(content)) def send_weichat(content): print('从微信发送消息:'+str(content)) def send_email(content): print('从email发送消息:'+str(content)) def run(): content = '我是阳过' send_qq(content) send_weichat(content) send_email(content) if __name__ == '__main__': run() ```  ### 方式2:基于django中间功能设计 ```python NOTICES = [ 'qq.send_qq.QQ', 'weichat.send_weichat.WeiChat', 'myemail.send_email.Email', # 包名不要与内置模块冲突 ] import os import sys BASE_DIR = os.path.dirname(__file__) print(BASE_DIR) sys.path.append(BASE_DIR) import importlib def send_message(content): for data in NOTICES: module, class_name = data.rsplit('.', maxsplit=1) # 切割字符串 print(module) module_obj = importlib.import_module(module) # 以字符串的形式导入模块拿到对象 obj = getattr(module_obj, class_name)() # 反射拿到类对象加括号产生对象 obj.send_message(content) # 执行类中的send_message方法 ``` 基于Django中间件 模拟Django中间件差不多的形式表现的  但最有一个拿到的都是类名 可importlib模块的最小单位都是py文件名 这怎么搞呢? start启动文件里面要用到notify包下所有的消息通知组件 那么导notify导的就是包里面的双下init.py  都添加到双下init.py中统一资源管理 导入配置文件settings.py 从右开始切割一次拿到就是字符串的py名文件路径 以及字符串的类名  再到启动文件中 如图:  那么怎样利用字符串去对象里拿一个名字呢? 想字符串、对象 >>> 想到就有反射:根据字符串获取对象对应的属性名(值)或方法名(函数体代码)  拿到类名加括号产生对象 对象点发送消息的方法  如图:  就实现跟Django中间件一样了 用你就写上 不用你注释掉  添加后注册  这样就实现了功能的插拔设计 ###总结: 利用到了内置模块importlib通过字符串导入模块、 以及rsplit从右开始max最大切割一次、 及反射getattr将模块名看成是对象再通过反射回去到对应模块中的字符串所对应的名字、 以及面向对象中的多态性当在使用面向对象的代码时在编写功能业务差不的代码时把他们的方法定义成相同的名字比较方便合理 Last modification:December 27th, 2022 at 09:26 pm © 允许规范转载 Support 如果觉得我的文章对你有用,请随意赞赏 ×Close Appreciate the author Sweeping payments
Comment here is closed