基本

DjangoでREST APIを作る|基本からDjango REST Frameworkまで

Django REST API Python

DjangoでREST APIを作る
基本からDjango REST Frameworkまで

DjangoでREST APIを構築する方法を解説。JsonResponseによるシンプルなAPIから、Django REST Frameworkを使った本格的なAPI開発まで学べます。

こんな人向けの記事です

  • DjangoでAPIを作りたい
  • Django REST Frameworkを使い始めたい
  • Serializerやパーミッションの仕組みを理解したい

Step 1REST APIとは

REST(Representational State Transfer)APIとは、HTTPメソッドを使ってリソースを操作する設計スタイルのWebAPIです。Webブラウザ向けにHTMLを返すのではなく、JSON形式のデータを返すことで、フロントエンド(React、Vue等)やモバイルアプリなど様々なクライアントからデータをやり取りできます。

RESTの基本原則

REST APIでは、URLが「リソース(データ)」を表し、HTTPメソッドが「操作」を表します。
例えば /api/articles/ というURLに対して、GETで取得、POSTで作成、のように操作を分けます。

HTTPメソッド操作URL例説明
GET取得(一覧)/api/articles/記事の一覧を取得
GET取得(詳細)/api/articles/1/ID=1の記事を取得
POST作成/api/articles/新しい記事を作成
PUT全体更新/api/articles/1/ID=1の記事を全体更新
PATCH部分更新/api/articles/1/ID=1の記事を部分更新
DELETE削除/api/articles/1/ID=1の記事を削除

REST APIのレスポンスは通常JSON形式で返されます。

JSON(レスポンス例)
{
    "id": 1,
    "title": "Djangoの基本",
    "content": "Djangoは...",
    "is_published": true,
    "created_at": "2026-02-18T10:30:00Z"
}
なぜREST APIが必要?

従来のDjangoはサーバー側でHTMLを生成して返す方式(テンプレートレンダリング)でした。しかし、フロントエンドとバックエンドを分離する現代の開発スタイルでは、バックエンドはデータ(JSON)だけを返し、画面の描画はフロントエンドが担当します。この「データだけ返すバックエンド」がREST APIです。

Step 2Django JsonResponseでシンプルなAPIを作る

Django REST Frameworkを使わなくても、Djangoの標準機能だけでシンプルなAPIは作れます。まずはJsonResponseを使った方法を見てみましょう。

models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    is_published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title
views.py(JsonResponseでAPI作成)
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import Article

# 記事一覧を取得するAPI
def article_list(request):
    if request.method == 'GET':
        articles = Article.objects.filter(is_published=True)
        data = []
        for article in articles:
            data.append({
                'id': article.id,
                'title': article.title,
                'content': article.content,
                'created_at': article.created_at.isoformat(),
            })
        return JsonResponse({'articles': data})

# 記事詳細を取得するAPI
def article_detail(request, pk):
    try:
        article = Article.objects.get(pk=pk)
    except Article.DoesNotExist:
        return JsonResponse({'error': '記事が見つかりません'}, status=404)

    if request.method == 'GET':
        data = {
            'id': article.id,
            'title': article.title,
            'content': article.content,
            'created_at': article.created_at.isoformat(),
        }
        return JsonResponse(data)

# 記事を作成するAPI
@csrf_exempt  # 本番では適切なCSRF対策を行う
def article_create(request):
    if request.method == 'POST':
        body = json.loads(request.body)
        article = Article.objects.create(
            title=body['title'],
            content=body['content'],
            is_published=body.get('is_published', False),
        )
        return JsonResponse({
            'id': article.id,
            'title': article.title,
        }, status=201)
urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('api/articles/', views.article_list, name='article-list'),
    path('api/articles/<int:pk>/', views.article_detail, name='article-detail'),
    path('api/articles/create/', views.article_create, name='article-create'),
]
JsonResponseの限界
  • シリアライズ(モデル→JSON変換)を毎回手動で書く必要がある
  • バリデーション処理を自分で実装しなければならない
  • 認証・パーミッション機能がない
  • HTTPメソッドの分岐を手動で書く必要がある
  • APIドキュメントの自動生成ができない

これらの問題を解決するのがDjango REST Framework(DRF)です。

Step 3Django REST Frameworkの導入

Django REST Framework(DRF)は、DjangoでREST APIを効率的に構築するためのサードパーティライブラリです。シリアライズ、バリデーション、認証、パーミッションなどAPIに必要な機能が一通り揃っています。

ターミナル(インストール)
pip install djangorestframework
settings.py(アプリ登録)
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',  # 追加
    'myapp',
]
DRFの全体像

DRFでは主に以下の3つのコンポーネントを使ってAPIを構築します。

コンポーネント役割対応するDjango機能
Serializerモデル ⇔ JSON の変換・バリデーションForm / ModelForm
APIView / ViewSetリクエスト処理・レスポンス返却View / CBV
RouterURL自動生成urls.py の手動定義

DRFを導入すると、Browsable API(ブラウザで操作できるAPI画面)が使えるようになります。これは開発中のAPIテストに非常に便利です。

settings.py(DRFの基本設定 - 任意)
REST_FRAMEWORK = {
    # レスポンスのデフォルトフォーマット
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',  # 開発用
    ],
    # ページネーション
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 20,
}

Step 4Serializerの基本

Serializer(シリアライザー)は、モデルインスタンスをJSONに変換したり、逆にリクエストデータをモデルインスタンスに変換する役割を持ちます。DjangoのFormに近い概念です。

serializers.py(基本のModelSerializer)
from rest_framework import serializers
from .models import Article

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'is_published', 'created_at']
        read_only_fields = ['id', 'created_at']
Meta属性説明
model対応するモデルクラス
fieldsAPIに含めるフィールド('__all__'で全フィールド)
read_only_fields読み取り専用フィールド(作成・更新時に無視)
exclude除外するフィールド(fieldsの代わりに使用)

Serializerを使うとバリデーションも簡単に追加できます。

serializers.py(カスタムバリデーション)
class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'is_published', 'created_at']
        read_only_fields = ['id', 'created_at']

    # フィールド単位のバリデーション
    def validate_title(self, value):
        if len(value) < 3:
            raise serializers.ValidationError('タイトルは3文字以上にしてください')
        return value

    # 複数フィールドにまたがるバリデーション
    def validate(self, data):
        if data.get('is_published') and not data.get('content'):
            raise serializers.ValidationError('公開する記事には本文が必要です')
        return data

Serializerを使ったシリアライズとデシリアライズの流れは以下の通りです。

Django shell(Serializerの動作確認)
# シリアライズ(モデル → JSON用dict)
article = Article.objects.first()
serializer = ArticleSerializer(article)
print(serializer.data)
# {'id': 1, 'title': '...', 'content': '...', ...}

# デシリアライズ(リクエストデータ → モデル)
data = {'title': '新しい記事', 'content': '本文...', 'is_published': True}
serializer = ArticleSerializer(data=data)
serializer.is_valid(raise_exception=True)  # バリデーション実行
serializer.save()  # DBに保存
ネストしたSerializer

リレーション先のデータも含めてJSONに変換できます。

serializers.py(ネストSerializer)
class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = ['id', 'text', 'created_at']

class ArticleDetailSerializer(serializers.ModelSerializer):
    comments = CommentSerializer(many=True, read_only=True)

    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'is_published', 'comments']

Step 5ViewSetとRouter

DRFには複数のビューの書き方がありますが、最も効率的なのがViewSet + Routerの組み合わせです。CRUDの処理とURLルーティングを最小限のコードで実現できます。

DRFのビューの種類

DRFでは用途に応じて複数のビュークラスが用意されています。上から順に抽象度が上がり、コード量が減ります。

クラス特徴ユースケース
APIView最も基本的。HTTPメソッドを手動で実装カスタムロジックが多いAPI
GenericAPIView + Mixin一覧・詳細・作成などをMixinで追加標準的なCRUDの一部だけ必要な場合
ModelViewSetCRUD全操作を自動提供標準的なCRUD API
views.py(APIViewで書く場合)
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Article
from .serializers import ArticleSerializer

class ArticleListView(APIView):
    def get(self, request):
        articles = Article.objects.filter(is_published=True)
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
views.py(ModelViewSetで書く場合 - 推奨)
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.filter(is_published=True)
    serializer_class = ArticleSerializer

たったこれだけで、一覧取得・詳細取得・作成・更新・削除の全APIが自動で作られます。

urls.py(Routerで自動ルーティング)
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet

router = DefaultRouter()
router.register('articles', ArticleViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

Routerが自動生成するURLは以下の通りです。

URLメソッドアクション
/api/articles/GET一覧取得(list)
/api/articles/POST作成(create)
/api/articles/{id}/GET詳細取得(retrieve)
/api/articles/{id}/PUT全体更新(update)
/api/articles/{id}/PATCH部分更新(partial_update)
/api/articles/{id}/DELETE削除(destroy)
カスタムアクションの追加

ViewSetに独自のエンドポイントを追加するには @action デコレータを使います。

views.py(カスタムアクション)
from rest_framework.decorators import action
from rest_framework.response import Response

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    # /api/articles/published/ でアクセス可能
    @action(detail=False, methods=['get'])
    def published(self, request):
        published = self.queryset.filter(is_published=True)
        serializer = self.get_serializer(published, many=True)
        return Response(serializer.data)

    # /api/articles/{id}/publish/ でアクセス可能
    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        article = self.get_object()
        article.is_published = True
        article.save()
        return Response({'status': '公開しました'})

Step 6認証とパーミッション

APIを公開する際、誰がアクセスできるか(認証)何ができるか(パーミッション)の設定は必須です。DRFには豊富な認証・パーミッション機能が組み込まれています。

settings.py(デフォルトの認証・パーミッション設定)
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}
認証クラス方式ユースケース
SessionAuthenticationDjangoのセッションブラウザからのアクセス
TokenAuthenticationトークンベースモバイルアプリ・外部API
BasicAuthenticationBasic認証テスト・開発時

TokenAuthenticationを使う場合の設定手順です。

settings.py / ターミナル(Token認証の設定)
# settings.py に追加
INSTALLED_APPS = [
    ...
    'rest_framework.authtoken',  # 追加
]

# マイグレーション実行
# python manage.py migrate

# トークン発行(Django shell)
# from rest_framework.authtoken.models import Token
# from django.contrib.auth.models import User
# user = User.objects.get(username='admin')
# token = Token.objects.create(user=user)
# print(token.key)  # このトークンをクライアントに渡す
ターミナル(トークンを使ったAPIリクエスト)
# curlでトークン認証のリクエスト
curl -H "Authorization: Token abc123your_token_here"      http://localhost:8000/api/articles/
主要なパーミッションクラス

DRFには以下のパーミッションクラスが組み込まれています。

パーミッション説明
AllowAny誰でもアクセス可能(認証不要)
IsAuthenticated認証済みユーザーのみ
IsAdminUser管理者ユーザーのみ
IsAuthenticatedOrReadOnly認証済みは全操作可、未認証は読み取りのみ
views.py(ViewSetにパーミッションを設定)
from rest_framework import viewsets, permissions
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            # 一覧・詳細は誰でもアクセス可能
            return [permissions.AllowAny()]
        # 作成・更新・削除は認証必須
        return [permissions.IsAuthenticated()]

プロジェクト固有の権限が必要な場合は、カスタムパーミッションを作成します。

permissions.py(カスタムパーミッション)
from rest_framework import permissions

class IsAuthorOrReadOnly(permissions.BasePermission):
    """
    記事の作成者のみ編集・削除可能。
    それ以外のユーザーは読み取りのみ。
    """
    def has_object_permission(self, request, view, obj):
        # GET, HEAD, OPTIONS は全員許可
        if request.method in permissions.SAFE_METHODS:
            return True
        # 書き込み系は作成者のみ
        return obj.author == request.user
views.py(カスタムパーミッションの適用)
from .permissions import IsAuthorOrReadOnly

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsAuthorOrReadOnly]

    def perform_create(self, serializer):
        # 作成時に自動でauthorを設定
        serializer.save(author=self.request.user)

REST API構築チェックリスト

  • REST APIの基本概念(リソース + HTTPメソッド)を理解した
  • JsonResponseでシンプルなAPIを作れるようになった
  • Django REST Frameworkをインストール・設定できた
  • ModelSerializerでモデルのシリアライズ・バリデーションができた
  • ModelViewSet + Routerで最小コードのCRUD APIを構築できた
  • 認証(Token認証)とパーミッションの設定ができた