ViewSetsとは?
参考:公式ドキュメント
Django REST FrameworkのViewSetは、いくつかのビューの処理を1つのクラスにまとめています。
例えば、データを一覧表示したり、新しいデータを作成したり、既存のデータを更新したりする処理を1つのクラスでまとめて行えます。
普通のビューと違って、GETやPOSTなどのメソッドを使わず、list()
(一覧)やcreate()
(作成)などのアクションを使います。
URL設定はas_view()メソッドを使って行い、通常はルーターを使用してViewSetを登録します。
例えば、以下のようにUserViewSetを定義して、その中につけたい処理をメソッドとして追加して使います。
class UserViewSet(viewsets.ViewSet):
def list(self, request):
pass # ユーザー一覧の取得
def create(self, request):
pass # 新しいユーザーの作成
def retrieve(self, request, pk=None):
pass # 特定のユーザー情報の取得
def update(self, request, pk=None):
pass # ユーザー情報の更新
def destroy(self, request, pk=None):
pass # ユーザーの削除
ViewSetの標準アクション
Django REST FrameworkのViewSetを使うと、標準的なCRUD操作(Create、Retrieve、Update、Delete)を簡単に実装できます。これらの操作は、ViewSet内で以下のアクションとして自動的に提供されます。
- list(): データの一覧を取得する(HTTPメソッドはGET)
- create(): 新しいデータを作成する(HTTPメソッドはPOST)
- retrieve(): 特定のデータを1件取得する(HTTPメソッドはGET、主にID指定で1件取得)
- update(): データ全体を更新する(HTTPメソッドはPUT)
- partial_update(): データの一部を更新する(HTTPメソッドはPATCH)
- destroy(): データを削除する(HTTPメソッドはDELETE)
@action
デコレータでカスタムアクションを追加
@action
というデコレータ(特別な文字列)を使うと、自分でカスタムのアクションを作成できます。
標準のCRUD操作以外の特定の処理を追加したいときに便利です。
例えば、データベースの一部のデータを特別に処理したり、特定のフィルタをかけたデータを返したりするアクションを追加する際に使います。具体的にはユーザーのパスワードの変更や、記事の投稿、記事の削除などを作りたいときに使います。
class UserViewSet(viewsets.ModelViewSet):
@action(detail=True, methods=['post'])
def set_password(self, request, pk=None):
pass # パスワードの変更処理
@action(detail=True)
とすると、特定のユーザーに対してだけパスワード変更のリクエストを受け付けるようになります。逆にdetail=False
にすると、全ユーザに対するアクションとすることができます。
標準アクションとカスタムアクションの違い
標準アクション(list、create、retrieveなど)は、データの基本操作(一覧、作成、更新、削除)を行います。
カスタムアクション(@action
を使って定義したもの)は、基本操作以外の特別な処理(例えば、パスワード変更や特定のフィルタをかけたデータ取得など)を実行します。
ViewSetとルーター
通常、ViewSetを使うときはルーターを使います。これを使って、ViewSetのメソッドが行われるURLを設定します。
しかしDjango REST FrameworkのViewSetは細かく手動で定義せずともViewSetの各アクション(list、create、retrieveなど)を自動的にURLにマッピングしてくれます。
これにより、個別にURLを定義しなくても、listメソッドにはGET /users/のようにアクセスでき、retrieveメソッドにはGET /users/{id}/という形式でアクセスできるようになります。
もちろん、特定のURLにしたい場合は手動でマッピングをルーターに定義することも可能です。
自動マッピングを行う場合
from rest_framework.routers import DefaultRouter
from .views import UserViewSet
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = [
# ルーターによる自動生成されたURLパターンを含む
path('', include(router.urls)),
]
これにより、/users/などの標準的なURLマッピングが自動で作成されます。
このように書いた場合、各メソッドは以下のURLが割り当てられます。
listメソッドのURL
- URL: /users/
- HTTPメソッド: GET
- 処理内容: ユーザーの一覧を取得
retrieveメソッドのURL
- URL: /users/{id}/
- HTTPメソッド: GET
- 処理内容: IDで指定された1人のユーザーの詳細を取得
createメソッドのURL
- URL: /users/
- HTTPメソッド: POST
- 処理内容: 新しいユーザーを作成する
updateメソッドのURL
- URL: /users/{id}/
- HTTPメソッド: PUT
- 目的: 特定のユーザーの全情報を更新する
partial_updateメソッド
- URL: /users/{id}/
- HTTPメソッド: PATCH
- 処理内容: 特定のユーザーの情報を部分的に更新する
destroyメソッド
- URL: /users/{id}/
- HTTPメソッド: DELETE
- 処理内容: 特定のユーザーを削除する
手動で特定のURLマッピングを作成する場合
@action
を使わないで手動でURLを定義する場合、例えば「パスワードを変更する」というカスタムアクションを追加する際には、下記のようにpath()を使ってURLを定義します。
path('users/int:pk/set_password/', ...): pkで指定されたユーザーのパスワードを変更するアクションを手動で定義しています。
from django.urls import path
from .views import UserViewSet
user_list = UserViewSet.as_view({
'get': 'list',
'post': 'create'
})
user_detail = UserViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
urlpatterns = [
path('users/', user_list, name='user-list'),
path('users/<int:pk>/', user_detail, name='user-detail'),
# カスタムアクションを追加
path('users/<int:pk>/set_password/', UserViewSet.as_view({'post': 'set_password'}), name='user-set-password'),
]