Django中间件
(1)介绍
(2)如何自定义中间件
- 在项目名或者应用名下创建一个任意名称的文件夹
- 在该文件夹内创建一个任意名称的py文件
- 在该py文件内需要书写类(这个类必须继承MiddlewareMixin)
- 然后再这个类里面就可以自定义五个方法了
- (这五个方法并不是全部都需要书写,用几个书写几个)
- 需要将类的路径以字符串的形式注册到配置文件中才能生效
| 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', |
| '自己写的中间件的路径' |
| ] |
(3)process_request
- 请求来的时候需要经过每一个中间件里面的process_request方法
- 结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
- 如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
- 如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行,而是原路返回(检验失败不允许访问...)
- process_request方法就是用来做全局相关的所有限制功能
| MIDDLEWARE = [ |
| 'django.middleware.security.SecurityMiddleware', |
| 'django.contrib.sessions.middleware.SessionMiddleware', |
| 'cbv.mymiddleware.mydd.MyMiddleware' |
| 'cbv.mymiddleware.mydd.MyMiddleware2' |
| ] |
| from django.shortcuts import HttpResponse,render,redirect |
| from django.utils.deprecation import MiddlewareMixin |
| |
| |
| class MyMiddleware(MiddlewareMixin): |
| def process_request(self, request): |
| print('我是第一个自定义中间件里面的process_request方法') |
| return HttpResponse('我是第一个自定义中间件里面的process_request方法返回的数据') |
| |
| |
| class MyMiddleware2(MiddlewareMixin): |
| def process_request(self, request): |
| print('我是第二个自定义中间件里面的process_request方法') |
| return HttpResponse('我是第二个自定义中间件里面的process_request方法返回的数据') |

(4)process_response
- 响应走的时候需要经过每一个中间件里面的process_response方法
- 该方法有两个额外的参数request,response
- 该方法必须返回一个HttpResponse对象
- 默认返回的就是形参response
- 也可以返回自己的
- 顺序是按照配置文件中注册了的中间件从下往上依次经过
| from django.shortcuts import HttpResponse, render, redirect |
| from django.utils.deprecation import MiddlewareMixin |
| |
| |
| class MyMiddleware(MiddlewareMixin): |
| def process_request(self, request): |
| print('我是第一个自定义中间件里面的process_request方法') |
| return |
| |
| def process_response(self, request, response): |
| """ |
| |
| :param request: |
| :param response: 就是django后端返回给浏览器的内容 |
| :return: |
| """ |
| print('我是第一个自定义中间件里面的process_response方法') |
| return response |
| |
| class MyMiddleware2(MiddlewareMixin): |
| def process_request(self, request): |
| print('我是第二个自定义中间件里面的process_request方法') |
| return HttpResponse('我是第二个自定义中间件里面的process_request方法返回的数据') |
| |
| def process_response(self, request, response): |
| print('我是第二个自定义中间件里面的process_response方法') |
| return response |
| |
| |
| |
| |
| |


总结:
process_request方法是从上往下执行
process_response方法是从下往上执行
- 如果在第一个process_request方法就已经返回了HttpResponse对象,那么响应走的时候是会直接走同级别的process_response返回
| from django.shortcuts import HttpResponse, render, redirect |
| from django.utils.deprecation import MiddlewareMixin |
| |
| |
| class MyMiddleware(MiddlewareMixin): |
| def process_request(self, request): |
| print('我是第一个自定义中间件里面的process_request方法') |
| return HttpResponse('我是第一个自定义中间件里面的process_request方法返回的数据') |
| |
| def process_response(self, request, response): |
| """ |
| |
| :param request: |
| :param response: 就是django后端返回给浏览器的内容 |
| :return: |
| """ |
| print('我是第一个自定义中间件里面的process_response方法') |
| return response |
| |
| |
| |
| class MyMiddleware2(MiddlewareMixin): |
| def process_request(self, request): |
| print('我是第二个自定义中间件里面的process_request方法') |
| return HttpResponse('我是第二个自定义中间件里面的process_request方法返回的数据') |
| |
| def process_response(self, request, response): |
| print('我是第二个自定义中间件里面的process_response方法') |
| return response |

(5)process_view
- 路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该方法
- 顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
| def process_view(self, request, view_name, *args, **kwargs): |
| print(view_name, args, kwargs) |
| print('我是第一个自定义中间件里面的process_view方法') |
(6)process_template_response
- 返回的HttpResponse对象有render属性的时候才会触发
- 顺序是按照配置文件中注册了的中间件从下往上执行
| def process_template_response(self, request, response): |
| print('我是第一个自定义中间件里面的process_template_response方法') |
| return response |
| def index(request): |
| print('我是视图函数的index') |
| obj= HttpResponse('index') |
| def render(): |
| print('我是render') |
| return HttpResponse('render') |
| obj.render = render |
| return HttpResponse('index') |
(7)process_exception
- 当视图函数中出现异常的情况下触发
- 顺序是按照配置文件中注册了的中间件从下往上执行
| def process_exception(self, request, exception): |
| print('我是第一个自定义中间件里面的process_exception方法') |
| print(exception) |
Django中间件编程思想
(1)定义包
| def wechat(content): |
| print(f"wechat的通知:>>>{content}") |
| |
| |
| def QQ(content): |
| print(f"QQ的通知:>>>{content}") |
| |
| |
| def email(content): |
| print(f"email的通知:>>>{content}") |
(2)启动文件中启动包
| from send_message import * |
| |
| |
| def send_all(content): |
| wechat(content=content) |
| QQ(content=content) |
| email(content=content) |
| |
| |
| if __name__ == '__main__': |
| send_all("test") |
| wechat的通知:>>>test |
| QQ的通知:>>>test |
| email的通知:>>>test |
(3)升级版
| class WeChat(object): |
| def __init__(self): |
| |
| pass |
| |
| def send(self, content): |
| print(f"WeChat的消息 :>>>{content}") |
| class QQ(object): |
| def __init__(self): |
| |
| pass |
| |
| def send(self, content): |
| print(f"QQ的消息 :>>>{content}") |
| class Email(object): |
| def __init__(self): |
| |
| pass |
| |
| def send(self, content): |
| print(f"email的消息 :>>>{content}") |
| import settings |
| import importlib |
| |
| def send_all(content): |
| |
| for path_str in settings.MODEL_LIST: |
| model_path, class_name = path_str.rsplit('.', maxsplit=1) |
| |
| |
| |
| |
| models = importlib.import_module(model_path) |
| |
| cls = getattr(models, class_name) |
| |
| obj = cls() |
| |
| obj.send(content) |
| |
| |
| if __name__ == '__main__': |
| send_all('1') |
| MODEL_LIST = [ |
| 'model.email.Email', |
| 'model.QQ.QQ', |
| 'model.WeChat.WeChat', |
| ] |
| import model |
| |
| model.send_all('test') |
| email的消息 :>>> test |
| QQ的消息 :>>> test |
| WeChat的消息 :>>> test |
遵从Python中的鸭子类型
可以在功能文件中自定义功能文件添加或者注释
在 settings.py
文件中相关的路径注释掉或添加上去即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通