Django REST Framework 中 @action 裝飾器詳解

概述

@action 裝飾器是 Django REST Framework (DRF) 中 ViewSet 的一個核心功能,用于定義自定義路由方法。它允許開發者在標準的 CRUD 操作(list、create、retrieve、update、destroy)之外,創建符合特定業務需求的接口,并自動生成相應的 URL 路由。

參數詳解

1. methods - HTTP 方法配置

  • 類型: List[str]
  • 作用: 指定該動作響應哪些 HTTP 請求方法
  • 默認值: ['get'] (僅響應 GET 請求)
  • 示例:
    @action(methods=['post', 'put'], detail=True)
    def custom_action(self, request, pk=None):# 同時響應 POST 和 PUT 請求pass
    

2. detail - 操作級別配置

  • 類型: bool
  • 必填: 是
  • 作用: 決定動作是針對單個對象還是整個集合
  • 取值:
    • True: 針對單個對象,URL 中包含對象ID
    • False: 針對整個集合,URL 中不包含對象ID
  • 示例:
    # 單個對象操作: /users/{pk}/activate/
    @action(detail=True, methods=['post'])
    def activate(self, request, pk=None):pass# 集合操作: /users/recent/
    @action(detail=False, methods=['get'])
    def recent(self, request):pass
    

3. url_path - URL 路徑自定義

  • 類型: str
  • 作用: 自定義 URL 路徑段,覆蓋默認的方法名
  • 默認值: 使用被裝飾的方法名
  • 示例:
    @action(detail=True, methods=['post'], url_path='change-password')
    def set_password(self, request, pk=None):pass
    # 生成 URL: /users/{pk}/change-password/
    

4. url_name - 反向解析名稱

  • 類型: str
  • 作用: 定義反向解析時使用的名稱
  • 默認值: 方法名(下劃線替換為連字符)
  • 示例:
    @action(detail=True, url_name='user-activation')
    def activate(self, request, pk=None):pass
    # 反向解析: reverse('user-viewset-user-activation', kwargs={'pk': 1})
    

5. **kwargs - 額外配置參數

  • 類型: dict
  • 作用: 覆蓋視圖級別的配置設置
  • 常用選項:
    • permission_classes: 權限控制
    • authentication_classes: 認證方式
    • throttle_classes: 限流配置
    • renderer_classes: 響應渲染器
    • parser_classes: 請求解析器
    • serializer_class: 序列化器

實戰案例

用戶管理系統示例

from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from django.contrib.auth.models import User
from .serializers import UserSerializer, PasswordResetSerializerclass UserViewSet(viewsets.ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializer# 1. 密碼重置 - 單個對象操作@action(detail=True,methods=['post'],url_path='reset-password',permission_classes=[IsAuthenticated],serializer_class=PasswordResetSerializer)def reset_password(self, request, pk=None):user = self.get_object()serializer = self.get_serializer(data=request.data)serializer.is_valid(raise_exception=True)# 執行密碼重置邏輯user.set_password(serializer.validated_data['new_password'])user.save()return Response({'status': '密碼重置成功'},status=status.HTTP_200_OK)# 2. 獲取活躍用戶 - 集合操作@action(detail=False,methods=['get'],url_path='active-users',permission_classes=[IsAdminUser])def get_active_users(self, request):active_users = User.objects.filter(is_active=True)page = self.paginate_queryset(active_users)if page is not None:serializer = self.get_serializer(page, many=True)return self.get_paginated_response(serializer.data)serializer = self.get_serializer(active_users, many=True)return Response(serializer.data)# 3. 批量導入用戶 - 集合操作,文件上傳@action(detail=False,methods=['post'],url_path='bulk-import',permission_classes=[IsAdminUser],parser_classes=[MultiPartParser]  # 支持文件上傳)def bulk_import_users(self, request):import_file = request.FILES.get('file')if not import_file:return Response({'error': '請提供導入文件'},status=status.HTTP_400_BAD_REQUEST)# 執行批量導入邏輯try:imported_count = self.process_import_file(import_file)return Response({'status': f'成功導入 {imported_count} 個用戶','imported_count': imported_count})except Exception as e:return Response({'error': f'導入失敗: {str(e)}'},status=status.HTTP_400_BAD_REQUEST)# 4. 用戶統計信息 - 集合操作@action(detail=False, methods=['get'])def statistics(self, request):total_users = User.objects.count()active_users = User.objects.filter(is_active=True).count()staff_users = User.objects.filter(is_staff=True).count()return Response({'total_users': total_users,'active_users': active_users,'staff_users': staff_users,'inactive_users': total_users - active_users})# 輔助方法def process_import_file(self, import_file):# 實現文件處理邏輯return 10  # 返回導入的用戶數量

自動生成的路由

使用 DefaultRouter 注冊 ViewSet:

from rest_framework.routers import DefaultRouterrouter = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')urlpatterns = router.urls

生成的路由包括:

HTTP 方法URL 路徑調用的方法名方法類型操作級別說明
GET/users/list內置方法集合操作獲取用戶列表
POST/users/create內置方法集合操作創建新用戶
GET/users/{pk}/retrieve內置方法單個對象獲取指定用戶詳情
PUT/users/{pk}/update內置方法單個對象完整更新用戶信息
PATCH/users/{pk}/partial_update內置方法單個對象部分更新用戶信息
DELETE/users/{pk}/destroy內置方法單個對象刪除指定用戶
POST/users/{pk}/reset-password/reset_password自定義@action方法單個對象重置用戶密碼
GET/users/active-users/get_active_users自定義@action方法集合操作獲取所有活躍用戶列表
POST/users/bulk-import/bulk_import_users自定義@action方法集合操作批量導入用戶數據
GET/users/statistics/statistics自定義@action方法集合操作獲取用戶統計信息

詳細說明

1. 內置標準方法

ModelViewSet
這些方法是 Django REST Framework 的 ModelViewSet 自動提供的:

方法名作用對應 HTTP 方法
list查詢資源集合GET
create創建新資源POST
retrieve獲取單個資源GET
update完整更新資源PUT
partial_update部分更新資源PATCH
destroy刪除資源DELETE

2. 自定義 @action 方法

這些是通過 @action 裝飾器添加的自定義業務方法:

方法名@action 配置業務功能
reset_password@action(detail=True, methods=['post'])用戶密碼重置
get_active_users@action(detail=False, methods=['get'])篩選活躍用戶
bulk_import_users@action(detail=False, methods=['post'])批量導入用戶
statistics@action(detail=False, methods=['get'])統計數據分析

URL 路由生成規則

DRF 的路由器按照以下規則生成 URL:

  • 標準方法: /{model_name}//{model_name}/{pk}/
  • 自定義方法:
    • detail=True: /{model_name}/{pk}/{action_name}/
    • detail=False: /{model_name}/{action_name}/

高級用法

自定義權限和序列化器

from rest_framework import permissionsclass IsOwnerOrAdmin(permissions.BasePermission):def has_object_permission(self, request, view, obj):return obj == request.user or request.user.is_staff@action(detail=True,methods=['get'],permission_classes=[IsOwnerOrAdmin],serializer_class=UserDetailSerializer
)
def detailed_profile(self, request, pk=None):user = self.get_object()serializer = self.get_serializer(user)return Response(serializer.data)

組合多個動作

class ProductViewSet(viewsets.ModelViewSet):# ... 其他代碼 ...@action(detail=True, methods=['post'])def add_to_cart(self, request, pk=None):# 添加到購物車邏輯pass@action(detail=True, methods=['post'])def add_to_wishlist(self, request, pk=None):# 添加到收藏夾邏輯pass@action(detail=True, methods=['get'])def reviews(self, request, pk=None):# 獲取商品評論product = self.get_object()reviews = product.reviews.all()serializer = ReviewSerializer(reviews, many=True)return Response(serializer.data)

最佳實踐

  1. 明確操作級別: 始終明確設置 detail 參數,確保 URL 結構正確
  2. 合理使用 HTTP 方法: 根據操作性質選擇正確的 HTTP 方法
    • GET: 獲取數據
    • POST: 創建或執行非冪等操作
    • PUT/PATCH: 更新數據
    • DELETE: 刪除數據
  3. 適當的權限控制: 為每個動作設置合適的權限類
  4. 使用專用序列化器: 為不同的動作使用專門的序列化器
  5. 錯誤處理: 提供清晰的錯誤響應
  6. 文檔注釋: 為每個自定義動作添加詳細的文檔注釋

常見問題解答

Q: 什么時候應該使用 @action?

A: 當需要實現超出標準 CRUD 操作的業務邏輯時,如狀態變更、批量操作、統計查詢等。

Q: detail=True 和 detail=False 有什么區別?

A: detail=True 針對單個對象,URL 包含對象ID;detail=False 針對整個集合,URL 不包含對象ID。

Q: 如何為 @action 方法編寫測試?

A: 使用 DRF 的 APITestCase,像測試標準端點一樣測試自定義動作:

def test_reset_password_action(self):url = reverse('user-reset-password', kwargs={'pk': self.user.pk})response = self.client.post(url, {'new_password': 'newpass123'})self.assertEqual(response.status_code, status.HTTP_200_OK)

總結

@action 裝飾器是 DRF ViewSet 的強大擴展工具,它提供了:

  • 靈活性: 輕松創建自定義 API 端點
  • 一致性: 保持與標準 CRUD 操作一致的代碼風格
  • 自動化: 自動生成 URL 路由
  • 可配置性: 支持細粒度的權限、認證和序列化配置

通過合理使用 @action 裝飾器,可以構建出既符合 RESTful 原則又能滿足復雜業務需求的 API 接口。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/96394.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/96394.shtml
英文地址,請注明出處:http://en.pswp.cn/web/96394.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【重磅更新】RetroBoard 全面升級,讓敏捷回顧更高效、更安全、更貼心!

??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ??????? ???????…

中州養老:華為云設備管理接口開發全流程

需求分析點擊同步數據時,要把華為云的數據拉取到我們的系統中對于新增設備操作,實際上這些參數與華為云產品我們添加設備時的參數是一樣的表結構設計E-R圖數據庫字段接口分析對于設備中的數據,我們既要再IOT平臺存儲,又要在數據庫中存儲.之所以保存兩份數據的原因:IOT平臺中只是…

Llama-Factory微調Qwen2.5-VL從數據集制作到部署記錄

Llama-Factory微調Qwen2.5-VL從數據集制作到部署記錄 電腦環境配置: 1.ubuntu24 2.3090(24G) 3.Cuda12.9 一、數據集制作 我的數據集主要是對圖像內容進行描述 1.Label-studio制作數據集 這是最原始的從零開始制作數據集的方法,不建議這樣做!…

【藍橋杯真題67】C++數位和為偶數的數 第十五屆藍橋杯青少年創意編程大賽 算法思維 C++編程選拔賽真題解

C++數位和為偶數的數 第十五屆藍橋杯青少年創意編程大賽C++選拔賽真題 博主推薦 所有考級比賽學習相關資料合集【推薦收藏】 1、C++專欄 電子學會C++一級歷年真題解析 電子學會C++二級歷年真題解析

【計算機網絡 | 第11篇】寬帶接入技術及其發展歷程

文章目錄寬帶接入技術詳解數字傳輸系統技術演進早期電話網的傳輸技術演變數字傳輸系統技術演進:從碎片到統一寬帶接入技術 ADSLADSL的基本原理與非對稱特性DMT調制技術:多子信道并行傳輸ADSL接入網組成電話分離器的設計原理與優勢ADSL的升級:…

(論文速讀)SCSegamba:用于結構裂紋分割的輕量級結構感知視覺曼巴

論文題目:SCSegamba: Lightweight Structure-Aware Vision Mamba for Crack Segmentation in Structures(用于結構裂紋分割的輕量級結構感知視覺曼巴)會議:CVPR2025摘要:不同場景下的結構裂縫像素級分割仍然是一個相當…

《蘇超風云》亮相時尚大賞,成短劇行業發展新風向

當男頻短劇憑借《一品布衣》五天橫掃10億播放的數據宣告逆襲,短劇市場格局正經歷深刻洗牌。風口之下,頭條視聽、中皋文旅、國內時尚視覺與短視頻創作領域的頭部廠牌“大灣視頻”攜手下場,打造精品男頻短劇《蘇超風云》,劍指2025年…

HTML5新年元旦網站源碼

新年主題網站開發概述 本項目基于HTML5、CSS3與JavaScript技術棧,打造了一個功能豐富、交互體驗流暢的新年主題網站,涵蓋文化展示、互動娛樂與社交分享三大核心模塊,通過現代化前端技術實現沉浸式節日氛圍營造。 1.1、核心功能架構 網站采…

CentOS 7 下iscsi存儲服務配置驗證

一、環境說明 centos7服務器*2服務器ip:服務端10.10.10.186 客戶端10.10.10.184服務端存儲卷sda1提前關閉防火墻,或開放默認 iSCSI 使用 3260 端口 二、服務端(Target)配置 安裝 iSCSI target 服務 yum install -y targetcli syst…

立即數、棧、匯編與C函數的調用

一、立即數在 ARM 架構中,立即數是指在指令中直接編碼的常量值,而不是通過寄存器或內存引用的值立即數的特點編碼限制:ARM指令是固定長度的(32位),因此立即數不能占用太多位數。典型的算術和邏輯指令通常只…

貪心算法與動態規劃:數學原理、實現與優化

貪心算法與動態規劃:數學原理、實現與優化 引言:算法選擇的本質 在計算機科學領域,算法選擇的本質是對問題特征的數學建模與求解策略的匹配。貪心算法與動態規劃作為兩種經典的優化算法,分別在不同問題域展現出獨特優勢。本文將從…

Leetcode 刷題記錄 21 —— 技巧

Leetcode 刷題記錄 21 —— 技巧 本系列為筆者的 Leetcode 刷題記錄,順序為 Hot 100 題官方順序,根據標簽命名,記錄筆者總結的做題思路,附部分代碼解釋和疑問解答,01~07為C語言,08及以后為Java語言&#xf…

Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示

把這兩個開關打開,然后刷新gradle文件

Java中方法重寫與重載的區別

目錄 1. 方法重載 (Overload) 什么是方法重載? 重載的特點: 重載的示例: 重載的調用: 2. 方法重寫 (Override) 什么是方法重寫? 重寫的特點: 重寫的示例: 重寫的調用: 3.…

微信小程序發送訂閱消息-一次訂閱,一直發送消息。

實現思路長期訂閱要求太高,需要政府、公共交通等單位才有資格,所以只能使用一次性訂閱。 就像是買奶茶,下單以后,會彈出讓用戶訂閱消息那種。以買奶茶為例:用戶第一次下單成功,點擊了訂閱消息。(一般都有三…

408 Request Timeout:請求超時,服務器等待客戶端發送請求的時間過長。

408 Request Timeout 是 HTTP 狀態碼之一,表示客戶端在發送請求時,服務器等待的時間過長,最終放棄了處理該請求。此問題通常與網絡延遲、客戶端配置、服務器設置或者應用程序的性能有關。1. 常見原因1.1 客戶端問題網絡連接延遲或不穩定&…

MongoDB面試集錦

該書的使用的MongoDB版本是 4.2.01、什么是NoSQL數據庫?NoSQL和RDBMS有什么區別?在那些情況下使用和不使用NoSQL數據庫?NoSQL是非關系型數據庫,NoSQLNot Only SQL 。關系型數據庫采用的是結構化的數據,NoSQL采用的是鍵…

直擊JVM面試題

JVM組成 JVM JVM 就是 Java 程序的運行環境,它通過 類加載、字節碼執行、內存管理、GC、線程調度 等機制,讓 Java 實現了 跨平臺、自動內存管理和高效執行。 它是一個抽象的計算機,能執行以 字節碼(.class 文件) 為單…

地球系統模式(CESM)實踐技術應用及進階

目前通用地球系統模式(Community Earth System Model,CESM)在研究地球的過去、現在和未來的氣候狀況中具有越來越普遍的應用。CESM由美國NCAR于2010年07月推出以來,一直受到氣候學界的密切關注。近年升級的CESM2.0在大氣、陸地、海…

StarRocks導入數據-使用 Broker Load 進行異步導入

目錄 一、背景 二、實操 三、查看導入進度 一、背景 將hive庫數據表導入starrocks. 二、實操 LOAD LABEL user_behavior (DATA INFILE("hdfs://<hdfs_ip>:<hdfs_port>/user/amber/user_behavior_ten_million_rows.parquet")INTO TABLE user_behavior…