記事一覧へ戻る 本の順番で続きを読む

REST API設計 - Django REST Framework入門

Python3上級 | 2026/02/18 21:20

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で検索・ソート機能を追加