REST API設計 - Django REST Framework
DRFのセットアップ
pip install djangorestframework
# settings.py
INSTALLED_APPS = [
...
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
],
}
シリアライザ
# blog/serializers.py
from rest_framework import serializers
from .models import Post, Category
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ['id', 'name', 'slug']
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.username', read_only=True)
category = CategorySerializer(read_only=True)
category_id = serializers.PrimaryKeyRelatedField(
queryset=Category.objects.all(),
source='category', write_only=True
)
class Meta:
model = Post
fields = [
'id', 'title', 'slug', 'author_name',
'category', 'category_id', 'body',
'status', 'created_at'
]
read_only_fields = ['slug', 'created_at']
def validate_title(self, value):
if len(value) < 3:
raise serializers.ValidationError('タイトルは3文字以上必要です')
return value
ビューセット
# blog/views.py
from rest_framework import viewsets, permissions, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.select_related('author', 'category')
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
search_fields = ['title', 'body']
ordering_fields = ['created_at', 'title']
def perform_create(self, serializer):
serializer.save(author=self.request.user)
def get_queryset(self):
qs = super().get_queryset()
status = self.request.query_params.get('status')
if status:
qs = qs.filter(status=status)
return qs
@action(detail=False, methods=['get'])
def recent(self, request):
recent = self.get_queryset().order_by('-created_at')[:5]
serializer = self.get_serializer(recent, many=True)
return Response(serializer.data)
ルーター
# blog/urls.py
from rest_framework.routers import DefaultRouter
from .views import PostViewSet
router = DefaultRouter()
router.register('posts', PostViewSet)
urlpatterns = router.urls
# 自動で以下のURLが生成される:
# GET /posts/ -> list
# POST /posts/ -> create
# GET /posts/{id}/ -> retrieve
# PUT /posts/{id}/ -> update
# PATCH /posts/{id}/ -> partial_update
# DELETE /posts/{id}/ -> destroy
# GET /posts/recent/ -> recent(カスタムアクション)
まとめ
- DRFのシリアライザでモデルとJSON間の変換を定義
- ViewSetとRouterでCRUDエンドポイントを自動生成
perform_create でリクエストユーザーを自動設定
@action でカスタムエンドポイントを追加
- SearchFilter/OrderingFilterで検索・ソート機能を追加