背景:很多人寫 Django 時容易“什么都往 views 里塞”,結果項目一大就亂套了。
需要把 視圖層 / 業務層 / 數據層 等職責清晰分出來。
圖解說明
-
Client:瀏覽器 / App / 前端調用 API。
-
urls.py:定義 API 路由,把請求分發到對應的 ViewSet。
-
views.py:控制器層(類似 Spring Controller),只負責調度。
-
serializers.py:數據輸入/輸出格式化 & 校驗(類似 DTO/Validator)。
-
services.py:業務邏輯核心(類似 Service)。
-
models.py:數據庫 ORM(類似 Repository/DAO)。
-
tasks.py:異步任務(Celery/RQ 等),做發郵件/推送等耗時操作。
-
permissions.py:權限認證、用戶訪問控制。
-
utils.py:通用工具函數。
-
Database:最終的數據存儲。
下面是詳細的介紹
一、Django 的天然 MVC / MTV 結構
Django 官方稱之為 MTV 模式,其實和 Spring MVC 的思想一致,只是命名不同:
-
Model(模型) → 數據層
- 定義數據庫表(ORM)
- 封裝業務數據對象
- 數據校驗(字段約束)
-
Template(模板) → 表現層
- 前端渲染 HTML 的模板(如果是純 API 項目,模板層弱化)
-
View(視圖) → 控制層
- 接收請求、調用業務邏輯、返回響應(JSON/HTML)
不過在實際開發中,Django 的 View 很容易變肥,所以我們需要借鑒 Spring MVC 的 Service/Controller 分層思想,進行更合理的拆分。
二、推薦的 Django 分層邏輯
1. models.py(數據模型層)
- 定義數據庫結構(ORM)
- 約束字段規則(null、unique、default 等)
- 封裝一些跟數據緊密相關的方法(例如
User.objects.active_users()
)
👉 注意:不要在 model 里寫復雜的業務邏輯,它應該只管數據。
2. serializers.py(數據序列化 & 校驗層)
-
類似 Spring 里的 DTO + Validator
-
負責:
- 數據的輸入/輸出轉換(JSON ? Python 對象)
- 字段級/對象級校驗
- 定義 API 數據格式
👉 業務邏輯不要放這里,它只管“數據是否合法、怎么展示”。
3. views.py / api.py(控制器層)
-
類似 Spring 的 Controller
-
負責:
- 接收 HTTP 請求
- 調用 Service 層 處理邏輯
- 返回響應(Response/JsonResponse)
👉 只做 調度,不做業務。保持盡量輕量。
4. services.py(業務邏輯層,推薦新增)
-
類似 Spring 的 Service
-
封裝核心業務邏輯,便于復用和單元測試
-
例如:
class OrderService:@staticmethoddef create_order(user, items):# 校驗庫存# 扣減余額# 創建訂單# 觸發通知return order
👉 最重要的層,能避免 “胖 View” 問題。
5. tasks.py(異步任務層)
- 放 Celery/RQ/定時任務邏輯
- 例如發送郵件、推送通知、批量清理數據
👉 讓耗時操作異步化,保持 API 快速響應。
6. urls.py(路由層)
- 定義 API 路由,類似 Spring 的
@RequestMapping
- 邏輯不要寫在這里。
7. permissions.py / authentication.py
- 類似 Spring 的攔截器/過濾器
- 處理權限校驗、用戶認證
8. utils.py / helpers.py
- 存放通用工具函數(時間處理、加密、日志等)
- 避免重復造輪子
- 案例
用 Django REST framework (DRF) 做一個實際案例「訂單系統」
一、案例背景
我們做一個最簡單的訂單系統 API:
- 用戶下單
- 查詢訂單
- 支付訂單
涉及到的對象:User
、Order
。
涉及到的邏輯:下單、支付。
二、推薦目錄結構
項目叫 shop
,應用叫 orders
:
shop/
│
├── shop/
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
│
├── apps/
│ └── orders/
│ ├── models.py # 數據模型 (ORM)
│ ├── serializers.py # 序列化 & 校驗
│ ├── views.py # 控制器 (調度層)
│ ├── services.py # 業務邏輯層
│ ├── tasks.py # 異步任務 (如發郵件)
│ ├── permissions.py # 權限控制
│ ├── urls.py # 路由定義
│ └── utils.py # 工具方法
│
├── requirements.txt
└── manage.py
和 Spring MVC 對比:
- Controller →
views.py
- Service →
services.py
- Repository/DAO →
models.py
- DTO/VO →
serializers.py
- Filter/Interceptor →
permissions.py
或middleware
三、代碼示例(精簡版)
1. models.py(數據模型)
from django.db import models
from django.contrib.auth.models import Userclass Order(models.Model):user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="orders")product_name = models.CharField(max_length=100)price = models.DecimalField(max_digits=10, decimal_places=2)is_paid = models.BooleanField(default=False)created_at = models.DateTimeField(auto_now_add=True)def __str__(self):return f"Order({self.product_name}, {self.user.username})"
2. serializers.py(數據序列化 & 校驗)
from rest_framework import serializers
from .models import Orderclass OrderSerializer(serializers.ModelSerializer):class Meta:model = Orderfields = ["id", "product_name", "price", "is_paid", "created_at"]read_only_fields = ["id", "is_paid", "created_at"]
3. services.py(業務邏輯層)
from .models import Orderclass OrderService:@staticmethoddef create_order(user, product_name, price):return Order.objects.create(user=user, product_name=product_name, price=price)@staticmethoddef pay_order(order: Order):if order.is_paid:raise ValueError("訂單已支付")order.is_paid = Trueorder.save()return order
👉 優點:
- views 變得很輕,只做調度
- 業務邏輯放在
services.py
,可復用、可測試
4. views.py(控制器層)
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import Order
from .serializers import OrderSerializer
from .services import OrderServiceclass OrderViewSet(viewsets.ModelViewSet):queryset = Order.objects.all()serializer_class = OrderSerializerdef perform_create(self, serializer):# 下單邏輯交給 servicereturn OrderService.create_order(user=self.request.user,product_name=serializer.validated_data["product_name"],price=serializer.validated_data["price"],)@action(detail=True, methods=["post"])def pay(self, request, pk=None):order = self.get_object()try:order = OrderService.pay_order(order)return Response(OrderSerializer(order).data, status=status.HTTP_200_OK)except ValueError as e:return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
5. urls.py(路由層)
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import OrderViewSetrouter = DefaultRouter()
router.register(r"orders", OrderViewSet, basename="order")urlpatterns = [path("", include(router.urls)),
]
四、請求示例
- 創建訂單
POST /orders/
{"product_name": "iPhone 16","price": "8999.00"
}
- 查詢訂單
GET /orders/
- 支付訂單
POST /orders/1/pay/
五、為什么這是一個優秀的架構?
? 分層清晰:
views
:只負責 HTTP 請求和響應services
:封裝業務邏輯,可測試,可復用serializers
:只做數據驗證 & 轉換models
:只管數據庫
? 職責單一:每個文件只做一件事,方便維護。
? 可擴展:
- 想加支付網關?只改
services.py
。 - 想做異步發郵件?寫在
tasks.py
,不影響views.py
。
? 團隊協作友好:
- 前端/后端都清楚 API 長啥樣
- 后端開發知道邏輯放哪里,不會出現“胖 views”