Django 中间件 4 大钩子 & CBV vs FBV 对比实战

通过最小化 Demo 验证 Django 中间件的 4 个钩子函数,并对比类视图 (CBV) 与函数视图 (FBV) 的异同。


一、环境

项目 版本
Python 3.13
Django 6.0.5

项目结构:

复制代码
DjangoHook/
├── demo/
│   ├── middleware.py   ← 自定义中间件(4 钩子)
│   └── views.py        ← FBV + CBV 对比视图
├── screenshots/
└── middleware_demo.log  ← 中间件运行日志

二、中间件 4 个钩子函数

Django 中间件是请求/响应的"钩子链",可以在请求到达视图前/后、异常发生时插入自定义逻辑。

执行顺序遵循 洋葱模型:请求阶段从上到下穿过所有中间件,响应阶段反向穿回。

2.1 四个钩子一览

钩子 触发时机 返回值 执行方向
process_request(request) 请求进入,视图未确定 NoneHttpResponse ↓ 正向
process_view(request, view_func, view_args, view_kwargs) 路由匹配后、视图执行前 NoneHttpResponse ↓ 正向
process_exception(request, exception) 视图抛出异常时 NoneHttpResponse ↑ 反向
process_response(request, response) 响应返回前 HttpResponse ↑ 反向

2.2 核心源码

python 复制代码
# demo/middleware.py
class DemoMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        self.process_request(request)            # 钩子1
        response = self.get_response(request)    # → 内部触发钩子2、3
        response = self.process_response(request, response)  # 钩子4
        return response

    def process_request(self, request):
        log(f"1. process_request --- {request.path}")

    def process_view(self, request, view_func, view_args, view_kwargs):
        log(f"2. process_view --- {view_func.__name__}")

    def process_exception(self, request, exception):
        log(f"3. process_exception --- {type(exception).__name__}: {exception}")

    def process_response(self, request, response):
        log(f"4. process_response --- {response.status_code}")
        return response

2.3 实验验证

分别请求正常视图和异常视图,观察中间件日志:

结论

  • 正常路径process_requestprocess_view → 视图执行 → process_response
  • 异常路径process_requestprocess_view → 视图抛异常 → process_exceptionprocess_response

浏览器截图如下------

正常请求 (FBV hello)

异常请求 (FBV exception)

2.4 洋葱模型图解

复制代码
  请求 ──────────────────────────────→ 响应
  ┌─────────────────────────────────────────┐
  │  1.process_request()    4.process_response()  │
  │         ↓                      ↑                │
  │  2.process_view()        3.process_exception()  │
  │         ↓                      ↑                │
  │      ┌──────────────────┐                    │
  │      │     视图函数      │                    │
  │      └──────────────────┘                    │
  └─────────────────────────────────────────┘

三、CBV vs FBV 对比

FBV (Function-Based View) 和 CBV (Class-Based View) 都能处理 HTTP 请求,核心差异在于 代码组织方式

3.1 最简示例

python 复制代码
# ========== FBV ==========
def hello_fbv(request):
    return HttpResponse("Hello from FBV!")

# ========== CBV ==========
class HelloCBV(View):
    def get(self, request):
        return HttpResponse("Hello from CBV!")

浏览器截图:

FBV CBV

3.2 处理多种 HTTP 方法

python 复制代码
# ========== FBV: 手动判断 request.method ==========
@csrf_exempt
def api_fbv(request):
    if request.method == "GET":
        return JsonResponse({"method": "GET", "type": "FBV"})
    elif request.method == "POST":
        data = json.loads(request.body) if request.body else {}
        return JsonResponse({"method": "POST", "type": "FBV", "received": data})
    return JsonResponse({"error": "Method not allowed"}, status=405)

# ========== CBV: 方法名自动分发 ==========
@method_decorator(csrf_exempt, name='dispatch')
class ApiCBV(View):
    def get(self, request):
        return JsonResponse({"method": "GET", "type": "CBV"})

    def post(self, request):
        data = json.loads(request.body) if request.body else {}
        return JsonResponse({"method": "POST", "type": "CBV", "received": data})

3.3 对比总结

维度 FBV CBV
代码量 (简单场景) 更少 稍多
代码量 (多方法场景) 手动 if/elif 方法自动分发
HTTP 方法分发 手动判断 request.method 自动映射 get() → GET, post() → POST
复用方式 @decorator 继承 + Mixin
可读性 函数体膨胀 每个方法职责单一
Django 内置通用视图 不支持 ListView, DetailView

3.4 何时用哪个?

  • 逻辑简单、单一功能 → FBV,例如:重定向、简单 API、健康检查
  • CRUD 操作、多种 HTTP 方法 → CBV,例如:REST API 资源、表单处理
  • 需要复用 Django 内置视图 → CBV,例如:分页列表、详情页

四、路由配置

python 复制代码
# DjangoHook/urls.py
from django.urls import path
from demo import views

urlpatterns = [
    # FBV
    path('fbv/hello/',     views.hello_fbv,       name='fbv_hello'),
    path('fbv/api/',       views.api_fbv,         name='fbv_api'),
    path('fbv/exception/', views.exception_fbv,   name='fbv_exception'),

    # CBV
    path('cbv/hello/',     views.HelloCBV.as_view(),      name='cbv_hello'),
    path('cbv/api/',       views.ApiCBV.as_view(),        name='cbv_api'),
    path('cbv/exception/', views.ExceptionCBV.as_view(),  name='cbv_exception'),
]

注意 CBV 必须调用 .as_view() 将类转换为可调用的视图函数。


相关推荐
yaoxin5211234 小时前
462. Java 反射 - 获取声明类与封闭类
java·开发语言·python
中微极客4 小时前
解锁LLM开发全栈能力:Python + LangChain + RAG 工程实战指南
人工智能·python·langchain
hhzz4 小时前
Barbershop:基于GAN和分割Mask的图像合成技术——从理论到实战全解析
图像处理·人工智能·python·深度学习·计算机视觉
Ulyanov6 小时前
雷达导引头Python仿真框架:GPU加速、6-DOF模型与半实物仿真接口
开发语言·python·雷达信号处理·雷达导引头
列逍6 小时前
博客系统测试
自动化测试·python·性能测试
星云开发7 小时前
拒绝无效加班!用Python打造自动化办公流,附Word/PDF互转硬核代码
python
dream_home84077 小时前
图像算法模型NPU适配与算法服务实战指南
人工智能·python·算法·npu 图像服务
AIGS0017 小时前
跨越语义鸿沟:企业本体语义平台的构建与落地
java·人工智能·python·机器学习·人工智能ai大模型应用
李可以量化8 小时前
PTrade 量化策略实战:二八轮动策略深度解析(下)
python
Mx_coder8 小时前
8年Java开发者AI转型第二周:RAG检索优化-从60%到90%准确率的3个关键技巧 (Day 13-14)
人工智能·python