🔖
# 3.1 API 設計の実際(Django REST Framework 編)
API 設計の実際(Django REST Framework 編)
前回の記事では Django REST Framework(DRF)の基本 を紹介した。
CRUD API をすぐに作れるのが DRF の強みだが、業務システムで長期運用するには 設計の工夫 が欠かせない。
この記事では、実際の API 設計で気をつけているポイントを総論的に整理する。
1. Serializer の設計方針
DRF では ModelSerializer
を使うとモデルをそのまま JSON に変換できる。
ただし業務システムではケースごとに Serializer を使い分けることが多い。
よくあるパターン
-
一覧用と詳細用を分ける
-
OrderListSerializer
→ 一覧では軽量に(id, customer_name など最小限) -
OrderDetailSerializer
→ 詳細では関連情報も含めて返す
-
-
入力用と出力用を分ける
- 入力時は受け付ける項目を制限(フロントから total_amount を送らせない など)
-
ネスト構造の扱い
- 関連モデルを展開するか、id のみ返すかを場面で決める
2. バージョン管理
API は一度公開すると簡単には変えられない。
破壊的変更を避けるため、最初からバージョン管理を意識する。
- URL で明示する:
/api/v1/orders/
- 将来
/api/v2/
を並行稼働させることで移行をスムーズにできる - 廃止予定の API は deprecation warning を出すと親切
3. エラーハンドリング
統一されたエラーレスポンスを返すことが重要。
DRF のバリデーションや権限エラーをベースに、フォーマットを揃える。
例: バリデーションエラー
{
"error": "ValidationError",
"message": {
"customer_name": ["このフィールドは必須です。"]
}
}
例: 認可エラー
{
"error": "PermissionDenied",
"message": "この操作を実行する権限がありません。"
}
これを共通化しておくと、フロント側が処理しやすくなる。
4. フィルタリングと検索
業務システムでは「一覧 API に検索条件をつけたい」というニーズが多い。
-
django-filter
を利用して?customer_name=ABC&date_from=2024-01-01
のようなクエリパラメータ検索 -
ページネーションを標準化
-
limit / offset
方式 -
cursor
ベース方式(大量データでも安定)
-
レスポンスには count
, next
, previous
, results
を含めるのが DRF 標準。
5. パフォーマンスと N+1 対策
Serializer で関連モデルを展開するときに N+1 クエリが発生しがち。
よく使う対策
-
select_related
/prefetch_related
を活用 - Serializer で必要以上に関連モデルを展開しない
- 重い処理はキャッシュや非同期ジョブに逃がす
6. レスポンス設計のベストプラクティス
- id は必ず含める(更新やリンクに必要)
- 一覧と詳細で返す項目を変える
- フロントで使いやすい形にする(例: 金額は数値と文字列を両方返す)
{
"id": 1,
"customer_name": "株式会社テスト",
"total_amount": 50000,
"total_amount_display": "¥50,000"
}
まとめ
CRUD を自動生成できる DRF でも、実際の業務システムで長期運用するには以下が重要になる。
- Serializer の分割と設計方針
- バージョン管理
- エラーハンドリングの統一
- フィルタリング・検索の設計
- パフォーマンスと N+1 対策
- フロントで扱いやすいレスポンス設計
API 設計は「どう作るか」以上に「どう運用し続けるか」が大事。
具体的な実装パターン(Serializer の分割やエラーハンドリングのコード例) を掘り下げていく予定。
Discussion