Django REST Frameworkの@action(detail=False)とは?detail=Trueとの違いと使い分け
はじめに
Django REST Framework(DRF)でViewSetを使っていると、
カスタムエンドポイントを追加したい場面が出てきます。
そのときによく出てくるのが以下の記述です。
@action(detail=False)
最初に見たとき、
「
detail=Falseとはどういう意味なのか?Trueとどう違うのか?」
と疑問に思いました。
本記事では、DRFの@actionデコレーターとdetailオプションについて、解説します。
@actionとは
@actionは、ViewSetクラス内で任意のメソッドに対してURLルーティングを追加できるデコレーターです。
ルーティングの定義をカスタマイズせずに、GET, POSTなどのHTTPメソッドを割り当てることができます。
detail=Trueとdetail=Falseの違い
| オプション | 対象 | ルーティング | 使いどころ |
|---|---|---|---|
detail=True |
単一のオブジェクト | /items/{id}/foo/ |
個別のデータに対する処理(例:ステータス変更) |
detail=False |
一覧・全体 | /items/foo/ |
一覧に対する処理(例:集計、フィルター、バルク処理) |
実例
detail=True の場合
@action(detail=True, methods=['post'])
def deactivate(self, request, pk=None):
item = self.get_object()
item.is_active = False
item.save()
return Response({'status': 'deactivated'})
→ /items/1/deactivate/ のように、特定のIDに対して処理を行います。
detail=False の場合
@action(detail=False, methods=['get'])
def total(self, request):
total = Item.objects.count()
return Response({'total': total})
→ /items/total/ のように、全体に関する処理(一覧向け) となります。
どんなときに使う?
-
detail=False→ 一覧表示中の追加情報を表示したいとき
(例:件数、平均値など) -
detail=True→ 個別オブジェクトに対してアクションを追加したいとき
(例:アーカイブ、公開、承認など)
💥 よくある間違いパターン
❌ detail=False にすべきところを detail=True にした場合
例えば、一覧に対する処理(例:全件の集計)にもかかわらず detail=True を指定してしまうと、
URLは /items/{id}/xxx/ のような ID付きのものしか作られなくなります。
@action(detail=True, methods=['get']) # 本当は False にすべき
def total(self, request, pk=None):
...
この場合、/items/total/ にアクセスすると 404エラーになります。
「なぜかURLが存在しない」ように見えるので、意外とつまずきやすいポイントです。
❌ detail=True にすべきところを detail=False にした場合
今度は逆に、個別のオブジェクトに対する処理にもかかわらず detail=False にすると、
IDなしのURLしか作られず、対象のオブジェクトを取得できなくなります。
@action(detail=False, methods=['post']) # 本当は True にすべき
def deactivate(self, request, pk=None):
item = self.get_object() # ← ここでエラー
...
このような処理は /items/1/deactivate/ のようなURLが必要ですが、
detail=False だと /items/deactivate/ しか作られず、self.get_object() が動きません。
✅ ポイント
-
detail=True→ 単一オブジェクトに対する処理 -
detail=False→ 一覧・全体に対する処理
迷ったら、「URLにIDが必要な処理かどうか」で判断しましょう
まとめ
| パターン | エンドポイント例 | 主な用途 | 判断ポイント |
|---|---|---|---|
@action(detail=False) |
/items/total/ |
集計、一覧向けのカスタム処理 | IDが不要な処理か? |
@action(detail=True) |
/items/1/deactivate/ |
単一オブジェクトへの操作 | IDが必要な処理か? |
おわりに
DRFのViewSetは便利ですが、カスタムエンドポイントを書くときに
@actionのdetailの意味でつまずく人は少なくないと思います。
本記事が参考になれば幸いです。
Discussion