概述

@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…