💭
# 3.2 Serializer 設計の実装パターン(Django REST Framework)
前回の記事では API 設計の総論を紹介した。
今回はその中から特に重要な Serializer 設計 を掘り下げる。
Serializer は Django REST Framework(DRF)の中心的な仕組みであり、
- 入力のバリデーション
- モデルとの変換
- レスポンスの整形
を担う。
実務では「とりあえず ModelSerializer」では済まない場面が多いため、いくつかのパターンを押さえておくと便利。
1. シンプルに ModelSerializer を使う
最も基本的なパターン。小規模アプリや管理系 API ではこれで十分なことも多い。
# serializers.py
from rest_framework import serializers
from .models import Order
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = "__all__"
💡 AI プロンプト例
この Order モデルから CRUD API 用のシンプルな ModelSerializer を作ってください。
2. 一覧用と詳細用を分ける
一覧 API では軽量な項目だけを返し、詳細 API では関連情報も含めるようにする。
class OrderListSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ["id", "customer_name", "total_amount"]
class OrderDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ["id", "customer_name", "total_amount", "created_at", "items"]
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
def get_serializer_class(self):
if self.action == "list":
return OrderListSerializer
return OrderDetailSerializer
💡 AI プロンプト例
Order モデルに対して、一覧用と詳細用の Serializer を分けてください。
一覧用は id, customer_name, total_amount のみ、
詳細用は created_at, items も含めるようにしてください。
3. 入力用と出力用を分ける
入力時には受け付けないフィールド(例: id, created_at)を除外したいケース。
class OrderInputSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ["customer_name", "total_amount"]
class OrderOutputSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ["id", "customer_name", "total_amount", "created_at"]
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
def get_serializer_class(self):
if self.action in ["create", "update", "partial_update"]:
return OrderInputSerializer
return OrderOutputSerializer
💡 AI プロンプト例
Order モデルに対して、入力用と出力用の Serializer を分けてください。
入力用では id, created_at を含めず、出力用では含めてください。
4. ネストされた Serializer
関連モデルを展開して返すパターン。
(例: 注文と注文アイテム)
class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ["id", "product_name", "quantity", "price"]
class OrderDetailSerializer(serializers.ModelSerializer):
items = OrderItemSerializer(many=True, read_only=True)
class Meta:
model = Order
fields = ["id", "customer_name", "total_amount", "items"]
レスポンス例:
{
"id": 1,
"customer_name": "株式会社テスト",
"total_amount": 50000,
"items": [
{ "id": 1, "product_name": "商品A", "quantity": 2, "price": 10000 },
{ "id": 2, "product_name": "商品B", "quantity": 1, "price": 30000 }
]
}
💡 AI プロンプト例
Order モデルと OrderItem モデルがあります。
Order の詳細レスポンスで items を展開して返す Serializer を作ってください。
5. カスタムフィールド
モデルに存在しない値を返したい場合は SerializerMethodField を使う。
class OrderListSerializer(serializers.ModelSerializer):
total_amount_display = serializers.SerializerMethodField()
class Meta:
model = Order
fields = ["id", "customer_name", "total_amount", "total_amount_display"]
def get_total_amount_display(self, obj):
return f"¥{obj.total_amount:,}"
💡 AI プロンプト例
Order モデルの total_amount をフォーマットして total_amount_display として返す Serializer を作ってください。
6. バリデーションの追加
モデルだけでは表現できない制約を Serializer で補う。
class OrderInputSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ["customer_name", "total_amount"]
def validate_total_amount(self, value):
if value <= 0:
raise serializers.ValidationError("金額は 0 より大きい必要があります。")
return value
💡 AI プロンプト例
OrderInputSerializer に total_amount が 0 以下のときバリデーションエラーを返す実装を追加してください。
まとめ
Serializer 設計の実装パターンを整理すると次の通り。
- シンプルに
ModelSerializerを使う - 一覧用 / 詳細用に分ける
- 入力用 / 出力用に分ける
- ネスト構造を展開する
- カスタムフィールドで柔軟に拡張
- 独自のバリデーションを追加
さらに AI を活用する場合は、
最初はシンプルに指示 → 結果を確認 → 必要に応じて追加指示、という流れが効率的。
「Serializer を作って」と依頼し、期待通りでなければ
「一覧用と詳細用を分けて」「フォーマット済みのフィールドを追加して」と段階的に伝えることで、
人間の設計方針を反映したコードを効率よく得られる。
Discussion