django中间件
内容概要
django中间件简介
django中间件两个重要方法
django自定义中间件
django中间件三个了解方法
基于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',
]
自定义中间件
1.创建存储自定义中间件代码的py文件或目录(如果中间件很多)
2.产靠自带中间件的代码编写类并继承
3.在类中编写五个可以自定义的方法
4.一定要在配置文件注册中间件才可以生效
中间件可以定义五个方法,分别是:(主要的是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
- 请求来的时候从上往下依次经过每一个注册了中间件里面的该方法 如果没有则直接跳过
- 如果该方法自己返回了HttpResponse对象那么不在往后执行而是直接原路返回
process_response
- 响应走的时候从下往上依次经过每一个注册了的中间件里面的方法 如果没有则直接跳过
- 该方法有两个request和response形参response指代的就是后端想要返回给前端浏览器的数据 该方法必须返回该形参 也可以替换
如果在执行process_request方法的时候直接返回了HttpResponse对象那么会原路返回执行process_response不是执行所有
需要了解的
process_view
process_exception
process_template_response
自定义中间件实操
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)
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)
def process_exception(self,request,exception):
print('from mymiddleware01 exception')
3.process_template_response
视图函数/视图类返回的HttpResponse对象含有redner并且对应一个方法的时候自动触发(顺序同process_response)
一定要把接收的HttpResponse对象返回出去
def process_template_response(self,request,response):
print('from mymiddleware01 template_response')
return response
基于django中间件实现的插拔式设计
将各个功能制作成配置文件的字符串形式
如果想拥有该功能就编写对应的字符串
如果不想拥有则注释掉对应的字符串
补充知识
如果想用字符串导入模块
import importlib
s1 = 'bbb.b' # aaa.bbb.ccc.b
res = importlib.import_module(s1) # from aaa.bbb.ccc import b
print(res) # <module 'bbb.b' from 'D:\\pythonProject03\\djangomiddle\\bbb\\b.py'>
注意字符串的结尾最小单位只能是py文件 不能是py文件里面的变量名
Django的settings文件里好多都是字符串 但是呢都是不简单的字符串
每一个字符串对应着一个py文件就代表着一个特定的功能
如果你想这个字符串有这个功能就加上 不想用就直接注释点
那么如何利用字符串导模块?
在纯python情况下
利用字符串导模块 内置模块importlib
如图:
按照点号从右开始切割一个 它的底层还是按照from导模块的句式
局限性这个模块的最小单位是py文件名 不能到py文件里的变量名
需求分析:
模拟编写一个消息通知功能(微信、qq、邮箱)
通过点击一个按钮就能触发消息
方式1:简单版 基于函数封装
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中间功能设计
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将模块名看成是对象再通过反射回去到对应模块中的字符串所对应的名字、
以及面向对象中的多态性当在使用面向对象的代码时在编写功能业务差不的代码时把他们的方法定义成相同的名字比较方便合理
标签:process,中间件,request,django,字符串,response From: https://www.cnblogs.com/clever-cat/p/17006409.html