Skip to content

Django REST Framework

**Django REST FrameworkDRF)**は、DjangoRESTful APIを迅速に構築するためのフレームワークです。APIの構築に必要な多くの機能を標準で提供しており、シリアライゼーション、ビュー、ルーティング、認証、パーミッションなどを簡単に実装できます。DRFDjangoの哲学である「バッテリー付属」に準拠しており、多くの一般的なAPI開発タスクを簡素化します。

まず、pipコマンドでDRFをインストールします。

Terminal window
pip install djangorestframework

次に、プロジェクトの**settings.py**ファイルに'rest_framework'INSTALLED_APPSに追加します。

settings.py
INSTALLED_APPS = [
...
'rest_framework',
]

これで、DRFをプロジェクトで利用する準備が整いました。

シリアライザーは、Djangoモデルのインスタンス(Pythonオブジェクト)を、JSONXMLのようなAPIで扱えるデータ形式に変換(シリアライズ)する役割を担います。また、その逆の変換(デシリアライズ)も行い、受信したデータを検証し、データベースに保存可能な形式に変換します。

  • serializers.ModelSerializer: 最もよく使われるシリアライザーです。モデルのフィールドからシリアライザーフィールドを自動的に生成し、バリデーションも自動で行います。提供された例のように、Metaクラスで変換対象のmodelfieldsを指定するだけで簡単に利用できます。
from rest_framework import serializers
from myapp.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email']

このシリアライザーは、Userモデルのインスタンスを、id, name, emailというキーを持つJSONデータに変換します。

シリアライザーを定義したら、次にビューを作成します。ビューは、APIリクエストを処理し、シリアライザーを使ってレスポンスを生成する役割を担います。DRFは、一般的なAPI操作を簡素化するために、いくつかの汎用ビューを提供しています。

  • generics.ListCreateAPIView: データのリスト表示と新規作成を一つのビューで処理します。
  • generics.RetrieveUpdateDestroyAPIView: 特定のデータ取得、更新、削除を処理します。
myapp/views.py
from rest_framework import generics
from .models import User
from .serializers import UserSerializer
class UserListCreate(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserRetrieveUpdateDestroy(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer

これらのビューは、querysetで対象のモデルのデータセットを、serializer_classでデータ変換に使うシリアライザーを指定するだけで機能します。

最後に、作成したビューにアクセスするためのURLを設定します。

myproject/urls.py
from django.urls import path
from myapp.views import UserListCreate, UserRetrieveUpdateDestroy
urlpatterns = [
path('users/', UserListCreate.as_view(), name='user-list'),
path('users/<int:pk>/', UserRetrieveUpdateDestroy.as_view(), name='user-detail'),
]

これで、http://localhost:8000/users/にアクセスするとユーザー一覧を取得でき、http://localhost:8000/users/1/にアクセスするとIDが1のユーザー情報を取得できるようになります。

多くのAPIは、アクセスを制御する必要があります。DRFでは、**認証(Authentication)とパーミッション(Permission)**という2つのメカニズムでこれを実現します。

  • 認証: ユーザーが誰であるかを識別するプロセスです。DRFは、トークン認証、セッション認証、Basic認証など、多くの認証クラスを標準で提供しています。
  • パーミッション: 認証されたユーザーに、特定のアクション(データの読み取り、書き込み、削除など)を行う権限があるかどうかを判断するプロセスです。

これらの設定は、ビュークラスの属性として簡単に指定できます。

myapp/views.py
from rest_framework import generics, permissions
from .models import User
from .serializers import UserSerializer
class UserListCreate(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# 認証されたユーザーのみがアクセス可能
permission_classes = [permissions.IsAuthenticated]
class UserRetrieveUpdateDestroy(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
# 認証されたユーザーのみがアクセス可能。
# ユーザーがオブジェクトの所有者である場合にのみ、更新・削除を許可するカスタムパーミッションも可能。
permission_classes = [permissions.IsAuthenticated]

ListCreateAPIViewRetrieveUpdateDestroyAPIViewのように、複数のビューを個別に定義するのは手間がかかります。DRFは、この問題を解決するために**ビューセット(ViewSets)とルーター(Routers)**を提供しています。

  • ビューセット: 複数のAPIエンドポイント(一覧表示、詳細表示、作成、更新、削除など)のロジックを、一つのクラスにまとめたものです。
  • ルーター: ビューセットを自動的に分析し、対応するURLを自動生成します。これにより、手動でのURL設定が大幅に削減されます。

ビューセットとルーターを使うと、上記で作成した2つのビューを、一つのクラスと数行のURL設定にまとめることができます。

myapp/views.py
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
# ModelViewSetは、一覧表示、詳細表示、作成、更新、削除の操作を自動で提供
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
myproject/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from myapp.views import UserViewSet
# ルーターをインスタンス化
router = DefaultRouter()
# ビューセットを登録
router.register(r'users', UserViewSet)
urlpatterns = [
# ルーターが生成したURLをインクルード
path('', include(router.urls)),
]

この設定だけで、以下のURLが自動的に生成されます。

DRFには、APIエンドポイントのテストを簡単にするためのクライアントが付属しています。これにより、実際のHTTPリクエストを送ることなく、Pythonコードでビューの動作を検証できます。テストは、APIの品質を保証し、リファクタリングを安全に行うために不可欠です。

myapp/tests.py
from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework import status
from .models import User
from .serializers import UserSerializer
class UserAPITestCase(APITestCase):
def setUp(self):
# テスト用のデータを準備
self.user = User.objects.create(name='testuser', email='test@example.com')
self.url = reverse('user-list') # ユーザー一覧URL
self.detail_url = reverse('user-detail', kwargs={'pk': self.user.id}) # 詳細URL
def test_get_user_list(self):
"""ユーザー一覧を取得できるかテスト"""
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
# データベース内のデータとAPIレスポンスが一致するか検証
self.assertEqual(len(response.data), 1)
def test_create_user(self):
"""新しいユーザーを作成できるかテスト"""
data = {'name': 'newuser', 'email': 'new@example.com'}
response = self.client.post(self.url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(User.objects.count(), 2)
def test_update_user(self):
"""ユーザー情報を更新できるかテスト"""
data = {'name': 'updateduser'}
response = self.client.patch(self.detail_url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.user.refresh_from_db()
self.assertEqual(self.user.name, 'updateduser')

テストを実行するには、python manage.py test myapp コマンドを使用します。

8. ドキュメンテーションの自動生成

Section titled “8. ドキュメンテーションの自動生成”

APIの利用を容易にするため、DRFSwagger/OpenAPI形式のドキュメントを自動で生成する機能を提供しています。**drf-spectacular**のようなライブラリを導入することで、ビューとシリアライザーの定義から、エンドポイント、リクエスト/レスポンスのスキーマ、認証方法などを記述したインタラクティブなAPIドキュメントを自動生成できます。これにより、手動でドキュメントを作成・更新する手間が省けます。

pip install drf-spectacular を実行。

settings.py'drf_spectacular' を追加。

urls.py にドキュメント用のパスを追加。

myproject/urls.py
from django.urls import path, include
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, SpectacularRedocView
urlpatterns = [
# APIスキーマの生成
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
# Swagger UIによるインタラクティブなドキュメント
path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
# Redocによるドキュメント
path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
# 他のAPIエンドポイント
path('api/', include('myapp.urls')),
]

サーバーを起動し、/api/schema/swagger-ui/ にアクセスすると、以下のようなインタラクティブなAPIドキュメントが表示されます。

これらの機能は、DRFが単なるAPI構築ツールではなく、開発プロセス全体を効率化する総合的なフレームワークであることを示しています。テストとドキュメンテーションの自動化は、APIの信頼性を高め、チーム内での協業を円滑にする上で不可欠な要素です。

この内容で、Django REST Frameworkの主要な機能と開発プロセスについて、非常に包括的にまとまっています。他に追記するとすれば、ページネーションとフィルタリングについてです。これらは、大規模なデータセットを扱うAPIにとって不可欠な機能であり、DRFが標準で提供している重要な機能です。

大規模なデータセットを扱う場合、すべてのデータを一度に返すのではなく、ページごとに分割して返すページネーションが必要です。DRFは、この機能を簡単に実装するためのクラスを提供しています。

プロジェクト全体でデフォルトのページネーションスタイルを設定できます。

settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

この設定により、すべてのListAPIViewModelViewSetに自動でページネーションが適用され、?page=2?page_size=20のようなクエリパラメータでページングを制御できるようになります。

特定のビューのみでページネーションを有効にする場合は、ビュークラスに直接pagination_classを指定します。

myapp/views.py
from rest_framework import viewsets, pagination
from .models import User
from .serializers import UserSerializer
class UserPageNumberPagination(pagination.PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
pagination_class = UserPageNumberPagination

APIの利用者が特定の条件でデータを絞り込めるように、フィルタリングや検索機能は不可欠です。DRFは、これらの機能も簡単に実装できるライブラリを提供しています。

pip install django-filter

まず、Djangoフィルタリングライブラリをインストールします。

INSTALLED_APPS'django_filters'を追加し、デフォルトのフィルタバックエンドを設定します。

settings.py
INSTALLED_APPS = [
...,
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}

ビュークラスにfilterset_fieldsを追加するだけで、特定のフィールドでフィルタリングが可能になります。

myapp/views.py
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# 'name'と'email'フィールドでフィルタリングを有効化
filterset_fields = ['name', 'email']

この設定により、http://localhost:8000/users/?name=john のようなURLで、名前に'john'を含むユーザーをフィルタリングできるようになります。

SearchFilterを使用すると、複数のフィールドにわたるテキスト検索を簡単に行えます。

myapp/views.py
from rest_framework import viewsets, filters
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# 検索機能を追加
filter_backends = [filters.SearchFilter]
# 'name'と'email'フィールドで検索を可能にする
search_fields = ['name', 'email']

これにより、http://localhost:8000/users/?search=johnのようなURLで、nameまたはemail'john'が含まれるユーザーを検索できます。

これらの機能は、DRFが提供する**「バッテリー付属」**の哲学をさらに体現しており、複雑なAPI要件にも柔軟に対応できることを示しています。ページネーションとフィルタリングを組み合わせることで、効率的でユーザーフレンドリーなAPIを構築することができます。

APIのパフォーマンスは、ユーザーエクスペリエンスに直結します。DRFでは、以下の方法で性能を最適化できます。

  • 読み取り専用フィールド(Read-only fields: シリアライザーでread_only=Trueを設定すると、特定のフィールドを読み取り専用にできます。これにより、API利用者が更新や作成時に不必要なデータを送信するのを防ぎ、データ整合性を高めます。
myapp/serializers.py
class UserSerializer(serializers.ModelSerializer):
created_at = serializers.DateTimeField(read_only=True)
class Meta:
model = User
fields = ['id', 'name', 'email', 'created_at']
  • ネストされたシリアライザー(Nested serializers: 関連するモデルのデータを一つのAPIレスポンスに含める場合、ネストされたシリアライザーを使用します。これにより、クライアントが複数のAPIコールを送信する必要がなくなり、ネットワークのオーバーヘッドが削減されます。

例えば、Postモデルとそれに関連するCommentモデルがある場合、PostSerializer内にCommentSerializerをネストさせることができます。

  • プレフェッチとセレクト関連オブジェクト(Prefetch & Select related objects: DjangoORMObject-Relational Mapper)には、データベースクエリの数を減らすための強力なメソッドがあります。

    • select_related(): 外部キーで関連付けられた単一オブジェクトを、親オブジェクトと一緒に一度のクエリで取得します。
    • prefetch_related(): 多対多の関係や逆方向の外部キーで関連付けられた複数のオブジェクトを、別のクエリで取得し、Python内で結合します。

これらのメソッドは、ビューのquerysetに適用することで、APIが返すデータの取得効率を劇的に改善します。

# myapp/views.py (PostとCommentの例)
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
# Postと関連するすべてのCommentを一度のクエリで取得
queryset = Post.objects.all().prefetch_related('comments')
serializer_class = PostSerializer

これらの最適化手法は、APIのパフォーマンスを向上させ、スケーラビリティを確保する上で非常に重要です。DRFは、このような高度な要件にも対応できる柔軟な設計がされています。

これまでに網羅された内容は、Django REST Frameworkを使ったAPI開発の基礎から応用までを十分にカバーしています。他に付け加えるべきは、カスタムフィールドとバリデーションです。これらは、特定のビジネス要件に合わせてAPIのデータ形式や検証ロジックを柔軟に調整するために不可欠な要素です。

12. カスタムフィールドとバリデーション

Section titled “12. カスタムフィールドとバリデーション”

DRFは、標準のフィールドやバリデーション機能に加えて、独自のデータ形式や検証ルールを定義する機能を提供しています。

  • カスタムシリアライザーフィールド: serializers.Fieldを継承して独自のフィールドを作成することで、標準のフィールドでは対応できないカスタムなデータ形式を扱えます。例えば、データベースには整数で保存されているステータスコードを、APIレスポンスでは可読性の高い文字列に変換するといった場合に役立ちます。
myapp/serializers.py
from rest_framework import serializers
class StatusDisplayField(serializers.Field):
def to_representation(self, value):
# データベースの整数値を文字列に変換
status_map = {1: 'Active', 2: 'Inactive'}
return status_map.get(value, 'Unknown')
def to_internal_value(self, data):
# 受信した文字列をデータベースの整数値に変換
status_map = {'Active': 1, 'Inactive': 2}
return status_map.get(data)
  • カスタムバリデーション: DRFは、データ検証のための多くの組み込みバリデーターを提供していますが、ビジネスロジックに合わせた複雑な検証ルールが必要な場合があります。

    • フィールドレベルのバリデーション: 特定のフィールドの検証ロジックをvalidate_<field_name>メソッドとしてシリアライザーに定義します。
    myapp/serializers.py
    class UserSerializer(serializers.ModelSerializer):
    class Meta:
    model = User
    fields = ['id', 'name', 'email']
    def validate_name(self, value):
    # 名前に数字が含まれていないか検証
    if any(char.isdigit() for char in value):
    raise serializers.ValidationError("Name cannot contain numbers.")
    return value
    • オブジェクトレベルのバリデーション: 複数のフィールドを組み合わせて検証する場合、シリアライザーにvalidate()メソッドを定義します。
    myapp/serializers.py
    class AppointmentSerializer(serializers.Serializer):
    start_date = serializers.DateTimeField()
    end_date = serializers.DateTimeField()
    def validate(self, data):
    # 終了日時が開始日時より後であることを検証
    if data['end_date'] < data['start_date']:
    raise serializers.ValidationError("End date must be after start date.")
    return data

これらのカスタム機能は、DRFの柔軟性を示しており、複雑なデータモデルやビジネス要件を持つAPIを構築する上で非常に役立ちます。これにより、DRFは単なるCRUD操作を超えた、堅牢で信頼性の高いAPIを迅速に開発するための強力なツールとなります。

DRFは多くの認証クラスを提供していますが、特定のサービスや要件に合わせた独自の認証方法を実装する必要がある場合があります。rest_framework.authentication.BaseAuthenticationを継承して、カスタム認証クラスを作成できます。

例えば、カスタムヘッダーX-API-KEYを検証するAPIキー認証を実装する例です。

myapp/authentication.py
from rest_framework import authentication
from rest_framework import exceptions
from myapp.models import APIKey
class APIKeyAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
api_key = request.META.get('HTTP_X_API_KEY')
if not api_key:
return None # 認証スキップ
try:
key_obj = APIKey.objects.get(key=api_key)
except APIKey.DoesNotExist:
raise exceptions.AuthenticationFailed('Invalid API key.')
# 認証成功: (user, auth_token)のタプルを返す
return (key_obj.user, None)

このカスタム認証クラスを、ビューやsettings.pyに追加することで利用できます。

myapp/views.py
from rest_framework import generics
from .models import Post
from .serializers import PostSerializer
from .authentication import APIKeyAuthentication
class PostListAPIView(generics.ListAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
authentication_classes = [APIKeyAuthentication]

permissions.IsAuthenticatedなどの組み込みパーミッションだけでは不十分な場合、独自のパーミッションクラスを作成して、より詳細なアクセス制御を実装できます。rest_framework.permissions.BasePermissionを継承し、has_permissionメソッドとhas_object_permissionメソッドをオーバーライドします。

  • has_permission(self, request, view): オブジェクトレベルではなく、ビュー全体へのアクセスを許可するかどうかを判断します。
  • has_object_permission(self, request, view, obj): 特定のオブジェクトへのアクセスを許可するかどうかを判断します。

例えば、ユーザーが自身の投稿のみを編集・削除できるようにするカスタムパーミッションです。

myapp/permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
オブジェクトの所有者のみが編集を許可。
読み取りは誰でも可能。
"""
def has_object_permission(self, request, view, obj):
# 読み取りリクエストの場合は、常に許可
if request.method in permissions.SAFE_METHODS:
return True
# 書き込みリクエストの場合、オブジェクトの所有者であるかチェック
return obj.owner == request.user

このパーミッションをビューセットに適用すると、認証されたユーザーは自分の投稿だけを更新・削除でき、他のユーザーの投稿は読み取り専用となります。

myapp/views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from .permissions import IsOwnerOrReadOnly
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsOwnerOrReadOnly]

これらのカスタム認証とパーミッションの概念は、DRFの拡張性とセキュリティの高さを示しています。これにより、特定のビジネスロジックやセキュリティ要件に合わせた、非常に堅牢なAPIを構築することが可能になります。

これまでにご紹介した内容は、DRFの包括的な知識基盤を構築するのに十分なものです。これらの概念を組み合わせることで、ほとんどすべてのRESTful APIの要件に対応できるでしょう。

APIの進化に伴い、クライアントの互換性を維持しながら新しい機能を追加したり、既存の機能を変更したりする必要が出てきます。DRFは、この問題に対処するために、さまざまなバージョニングスキームを提供しています。

  • URLPathVersioning: URLにバージョン番号を含める最も一般的な方法です。
    • http://api.example.com/v1/users/
  • NamespaceVersioning: URLDjangoURL名前空間を使用する方法です。
    • http://api.example.com/users/ (v1の名前空間)
  • QueryParameterVersioning: クエリパラメータでバージョンを指定する方法です。
    • http://api.example.com/users/?version=1.0
  • HeaderVersioning: HTTPヘッダーでバージョンを指定する方法です。

settings.pyでデフォルトのバージョニングクラスを設定することで、プロジェクト全体に適用できます。

settings.py
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
}

各ビューにversioning_classを指定して、異なるバージョンごとに異なるシリアライザーやロジックを使用することも可能です。

DRFは、APIレスポンスの最終的なフォーマットを決定するために、**レンダラー(Renderers)**を使用します。デフォルトでは、JSONRendererが使われますが、XMLHTML、さらにはカスタムなフォーマットにも対応できます。

  • JSONRenderer: 最も一般的で、JSON形式のレスポンスを生成します。
  • BrowsableAPIRenderer: ブラウザからAPIにアクセスした際に表示される、インタラクティブなHTMLインターフェースを生成します。開発・デバッグ時に非常に便利です。

ビュークラスにrenderer_classes属性を設定することで、特定のビューに適用するレンダラーをカスタマイズできます。

myapp/views.py
from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
from rest_framework.response import Response
class MyAPIView(APIView):
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
def get(self, request, format=None):
return Response({'message': 'Hello, world!'})

この設定により、GETリクエストでブラウザからアクセスすると、HTMLの閲覧可能なAPIが表示され、curlなどでJSONを要求するとJSONレスポンスが返されます。

これらの機能は、DRFAPIのライフサイクル全体を考慮して設計されていることを示しており、単一の静的なAPIではなく、進化するサービスを構築するために不可欠な要素です。

Djangoには、manage.py経由で実行できる独自のコマンドを作成する機能があります。DRFプロジェクトでは、APIキーの自動生成、定期的なデータクリーンアップ、外部APIからのデータインポートなど、特定の管理タスクを自動化するために利用できます。

myapp/management/commands/create_api_keys.py
from django.core.management.base import BaseCommand
from myapp.models import APIKey, User
class Command(BaseCommand):
help = 'Creates an API key for each user who does not have one.'
def handle(self, *args, **options):
users_without_keys = User.objects.filter(apikey__isnull=True)
for user in users_without_keys:
APIKey.objects.create(user=user)
self.stdout.write(self.style.SUCCESS(f'Successfully created API key for user: {user.username}'))

このコマンドはpython manage.py create_api_keysで実行でき、管理タスクの自動化に便利です。

**シグナル(Signals)**は、特定のイベント(例:モデルが保存された、ユーザーがログインした)が発生したときに、関連する関数を自動的に実行させるための仕組みです。DRFのシリアライザーやビューで発生するイベントと連携させることで、柔軟な処理を実現できます。

たとえば、新しいユーザーが作成されたときに、自動でAPIキーを生成する処理をシグナルで実装できます。

myapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from myapp.models import APIKey
@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
APIKey.objects.create(user=instance)
myapp/apps.py
from django.apps import AppConfig
class MyappConfig(AppConfig):
name = 'myapp'
def ready(self):
import myapp.signals

この方法により、Userモデルが保存されるたびに、post_saveシグナルがトリガーされ、create_auth_token関数が実行されます。DRFModelViewSetListCreateAPIViewを介してユーザーが作成された場合でも、このシグナルが自動的に機能します。

これらの概念はDRFに特化したものではありませんが、DRFプロジェクトをDjangoの全体的なエコシステムと統合し、より効率的で自動化されたシステムを構築する上で非常に重要です。

大規模なAPIやトラフィックの多いAPIでは、データベースへのクエリ数を減らすことがパフォーマンス向上の鍵となります。DRFは、Djangoのキャッシングフレームワークと連携することで、APIレスポンスのキャッシングを簡単に実現できます。

  • ビューセット単位でのキャッシング: サービス全体で特定のビューセットのレスポンスをキャッシュする一般的な方法です。django-rest-framework-extensionsのような外部ライブラリを併用することで、より柔軟なキャッシュ戦略を実装できます。

  • ビュー単位でのキャッシング: method_decoratorを使用すると、特定のビューのメソッドのみをキャッシュできます。これは、頻繁にアクセスされるが更新頻度が低いAPIエンドポイントに特に有効です。

myapp/views.py
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
# 60秒間キャッシュする
@method_decorator(cache_page(60 * 1), name='dispatch')
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer

@method_decorator(cache_page(60 * 1), name='dispatch') をビューセットに追加することで、そのビューセットへのリクエストに対するレスポンスが60秒間キャッシュされます。これにより、同じリクエストが複数回発生した場合でも、データベースへのクエリは一度しか実行されません。

キャッシュの管理は、settings.pyで設定します。ローカルメモリ、ファイルシステム、データベース、またはRedisなどのバックエンドを使用できます。

これらのキャッシング機能は、DRFプロジェクトのパフォーマンスとスケーラビリティを劇的に向上させるための最後の重要なピースです。これで、DRFの基本的な概念から、開発、テスト、運用、そして性能最適化に至るまで、包括的な知識が網羅されました。