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() 将类转换为可调用的视图函数。


相关推荐
临沂GEO14 分钟前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白19 分钟前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲2 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)3 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机3 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor6924 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy5 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽5 小时前
真实即粗糙,光滑是伪造
人工智能·python
一次旅行5 小时前
Attention机制从数学到工程:拆解缩放点积+多头注意力|附可运行PyTorch实现与踩坑指南
人工智能·pytorch·python
泡干脆面就番茄5 小时前
NumPy 科学计算完全指南:从数组创建到广播机制
python·numpy