Django中间件实战:FBV/CBV日志全兼容
在 Django 开发中,中间件是请求、响应流程的「全局拦截器」,FBV/CBV是两种核心视图写法。本文带你从零实现自定义日志中间件,兼容函数视图和类视图,同时清晰对比两种视图的使用场景,轻松掌握非侵入式的请求增强能力!
一、实验核心目标
1. 学会在 Django 中自定义中间件,掌握请求 / 响应全流程拦截
2. 理清中间件执行顺序,实现请求日志、视图埋点、异常捕获
3. 对比 FBV(函数视图)和 CBV(类视图)写法,理解适用场景
4. 最终效果:访问任意接口,控制台自动打印请求路径、方法、视图名、响应状态码、异常信息
二、Django 中间件:全局请求「拦截器」
1. 核心概念
Django 中间件是介于浏览器请求和视图函数之间的钩子层,请求会先经过中间件,响应会再经过中间件返回浏览器,不修改业务代码就能实现全局功能增强。
2. 经典应用场景
- 统一请求日志记录
- 用户登录校验、IP 黑名单拦截
- 全局异常处理
- 响应头统一配置
- 接口访问埋点统计
思想类比:和 SpringBoot 的拦截器、AOP 完全一致,都是非侵入式的功能扩展!
3. 完整执行流程
浏览器发送请求 ↓ process_request(请求进入视图前) ↓ process_view(视图执行前) ↓ 执行 FBV/CBV 视图 ↓ 视图报错 → process_exception(异常捕获) ↓ process_response(响应返回前) ↓ 浏览器接收响应4. 核心方法说明
| 方法 | 执行时机 | 核心作用 |
|---|---|---|
| process_request | 请求刚进入 | 获取请求方法、路径,做基础校验 |
| process_view | 视图执行前 | 获取视图名称、参数,埋点日志 |
| process_exception | 视图报错时 | 捕获全局异常,打印错误信息 |
| process_response | 响应返回前 | 修改响应头、记录状态码 |
三、实战第一步:自定义日志中间件
1. 创建中间件文件
在你的 Django 应用目录下,新建middleware.py文件,编写兼容 FBV/CBV 的日志中间件:
运行
# 你的应用名/middleware.py from django.utils.deprecation import MiddlewareMixin class SimpleLogMiddleware(MiddlewareMixin): """ 自定义日志中间件: 1. 记录请求入口信息 2. 打印即将执行的视图(兼容FBV/CBV) 3. 捕获视图全局异常 4. 记录响应状态码 + 自定义响应头 """ def process_request(self, request): """请求进入视图前执行""" print(f"\n[中间件] 请求进入:{request.method} {request.path_info}") def process_view(self, request, view_func, view_args, view_kwargs): """视图执行前执行,核心:兼容FBV和CBV获取真实视图名""" # 兼容CBV:获取类视图的类名 view_class = getattr(view_func, "view_class", None) view_name = view_class.__name__ if view_class else view_func.__name__ print(f"[中间件] 即将执行视图:{view_name}") print(f"[中间件] 视图参数:args={view_args}, kwargs={view_kwargs}") print(f"[中间件] 请求详情:path={request.path_info}, method={request.method}") def process_exception(self, request, exception): """视图执行报错时自动触发""" print(f"[中间件] 视图异常:{exception}") def process_response(self, request, response): """响应返回浏览器前执行""" print(f"[中间件] 响应返回:状态码={response.status_code}") # 自定义响应头,标记中间件已生效 response["X-Request-Log"] = "enabled" return response✅关键技巧:process_view中通过view_class兼容 CBV,避免类视图只显示view而无法识别真实类名!
2. 注册中间件(核心步骤)
打开项目settings.py,在MIDDLEWARE列表末尾注册自定义中间件:
运行
# 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.中间件类名 '你的应用名.middleware.SimpleLogMiddleware', ]注意:中间件顺序决定执行优先级,请求从上到下执行,响应从下到上执行。
四、实战第二步:编写 FBV + CBV 视图
我们同时实现两种视图,测试中间件的兼容性。
1. FBV 函数视图(Function Based View)
适合简单业务,代码直接易懂:
运行
# 你的应用名/views.py from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt # 忽略CSRF校验,方便测试 def login_fbv(request): """FBV登录视图:手动判断请求方法""" if request.method == "GET": return HttpResponse("GET 请求 - FBV 视图") if request.method == "POST": # 获取表单参数 username = request.POST.get("user") password = request.POST.get("pwd") # 简单校验 if username == "admin" and password == "123456": return HttpResponse("登录成功 - FBV 视图") return HttpResponse("登录失败 - FBV 视图") # 不支持的请求方法 return HttpResponse("仅支持GET/POST", status=405)2. CBV 类视图(Class Based View)
适合复杂业务,按请求方法拆分逻辑,结构清晰:
运行
# 你的应用名/views.py from django.http import HttpResponse from django.views import View from django.views.decorators.csrf import csrf_exempt class LoginCBV(View): """CBV登录视图:自动匹配GET/POST方法""" @csrf_exempt def dispatch(self, request, *args, **kwargs): # 重写dispatch,忽略CSRF校验 return super().dispatch(request, *args, **kwargs) def get(self, request): """自动处理GET请求""" return HttpResponse("GET 请求 - CBV 视图") def post(self, request): """自动处理POST请求""" username = request.POST.get("user") password = request.POST.get("pwd") if username == "admin" and password == "123456": return HttpResponse("登录成功 - CBV 视图") return HttpResponse("登录失败 - CBV 视图")五、实战第三步:配置路由
在应用的urls.py中配置两个测试接口,CBV 必须调用as_view()转换为 Django 可识别的函数:
运行
# 你的应用名/urls.py from django.urls import path from . import views urlpatterns = [ # FBV 路由:直接写函数名 path('login/fbv/', views.login_fbv, name='login_fbv'), # CBV 路由:必须调用 as_view() path('login/cbv/', views.LoginCBV.as_view(), name='login_cbv'), ]六、运行项目 + 测试效果
1. 启动 Django 服务
运行
# 检查项目配置 python manage.py check # 启动服务 python manage.py runserver2. 访问测试接口
浏览器访问:
- FBV:
http://127.0.0.1:8000/login/fbv/ - CBV:
http://127.0.0.1:8000/login/cbv/
3. 控制台输出效果(中间件生效!)
[中间件] 请求进入:GET /login/fbv/ [中间件] 即将执行视图:login_fbv [中间件] 视图参数:args=(), kwargs={} [中间件] 请求详情:path=/login/fbv/, method=GET [中间件] 响应返回:状态码=200 [中间件] 请求进入:GET /login/cbv/ [中间件] 即将执行视图:LoginCBV [中间件] 视图参数:args=(), kwargs={} [中间件] 请求详情:path=/login/cbv/, method=GET [中间件] 响应返回:状态码=2004. 异常捕获测试
在 FBV 视图中手动制造错误,测试异常拦截:
运行
@csrf_exempt def login_fbv(request): 1 / 0 # 制造除零异常 # ... 原有代码刷新接口,控制台自动打印异常:
[中间件] 视图异常:division by zero测试完成后删除错误代码即可!
七、FBV vs CBV 终极对比
| 对比维度 | FBV 函数视图 | CBV 类视图 |
|---|---|---|
| 全称 | Function Based View | Class Based View |
| 编写方式 | 普通函数 | 继承 View 的类 |
| 请求处理 | 手动判断request.method | 自动匹配get()/post() |
| 代码结构 | 简洁直接,代码集中 | 结构清晰,按方法拆分 |
| 扩展性 | 弱,复杂业务易臃肿 | 强,支持继承 / 重写 |
| 路由写法 | views.login_fbv | views.LoginCBV.as_view() |
| 适用场景 | 简单接口、小功能页面 | 复杂业务、需要复用逻辑 |
开发建议:小功能用 FBV 快速开发,复杂业务用 CBV 规范代码!
八、实验总结
1. 中间件核心价值:非侵入式实现全局功能,无需修改每个视图就能统一记录日志、捕获异常。
2. 执行顺序:process_request→process_view→ 视图 →process_exception(异常)→process_response。
3. 兼容技巧:process_view中通过view_class兼容 CBV 视图,精准获取视图名称。
4. 视图选择:简单业务 FBV 首选,复杂业务 CBV 更优。
这套中间件 + 视图的组合,是Django开发中全局日志、权限校验、异常处理的标准方案,直接复用就能提升项目开发效率!
【附件】
相关所有代码可点击下方链接见详情:
django-middleware-fbv-cbv-demo: Django 自定义中间件实战,实现请求日志、异常捕获,同时对比 FBV 函数视图与 CBV 类视图的写法与执行流程。https://gitee.com/Zhang-Siyu0066/django-middleware-fbv-cbv-demo
