DRF中的action装饰器介绍
在 Django REST Framework (DRF) 中,@action 装饰器主要用于为 ViewSet 添加自定义的操作。它使得你能够定义超出标准 CRUD 操作(list、create、retrieve、update、destroy)之外的额外行为。这些自定义操作通常用来处理一些特殊的业务逻辑,或是某些针对特定资源的额外功能。
主要用途
- 添加自定义的业务逻辑
- 定义额外的 API 端点
- 增强标准视图集(ViewSet)的功能
1. 添加自定义的业务逻辑
@action 让你可以为 ViewSet 创建不属于标准 CRUD 操作的自定义方法。例如,获取某个特定模型的某些统计信息、进行复杂的过滤操作或是处理一些与业务逻辑相关的功能。
示例:获取课程的统计信息
假设你有一个 Course 模型,并希望在 CourseViewSet 中添加一个返回某些课程统计信息的操作:
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import Course
from .serializers import CourseSerializer
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(detail=False, methods=['get'], url_path='summary')
def get_summary(self, request):
total_courses = Course.objects.count()
average_price = Course.objects.aggregate(Avg('price'))['price__avg']
return Response({
'total_courses': total_courses,
'average_price': average_price
})说明:
- 业务逻辑:此操作计算课程的总数和平均价格。
- @action:它为 CourseViewSet 添加了一个名为 get_summary 的操作,这个操作不是标准的 CRUD 操作,而是一个返回课程统计信息的自定义操作。
访问:
可以通过 GET /api/courses/summary/ 访问该自定义的操作,返回课程的统计信息。
2. 定义额外的 API 端点
通过 @action,你可以为资源定义额外的端点。这些端点可能涉及对单一资源或整个资源集合的操作,通常用于处理一些特定的查询或命令。
示例:为单个课程添加一个操作
如果你希望为某个课程提供一个“发布”操作,使课程的状态变为已发布,可以使用 @action 装饰器来实现。
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(detail=True, methods=['post'], url_path='publish')
def publish_course(self, request, pk=None):
course = self.get_object()
course.status = 'published'
course.save()
return Response({'status': 'Course published successfully'})说明:
- @action(detail=True):此操作是针对单个资源的,因此 detail=True,意味着这个操作会针对某个特定课程(例如 GET /api/courses/1/publish/)。
- methods=['post']:指定这个操作支持 POST 请求。
- 业务逻辑:将课程的状态更改为 published。
访问:
可以通过 POST /api/courses/{id}/publish/ 访问此操作,发布特定课程。
3. 增强标准视图集(ViewSet)的功能
通过 @action,你可以为 ModelViewSet 或 ViewSet 添加额外的逻辑,扩展标准的 list、retrieve、create、update 和 destroy 等操作。例如,你可以添加一个额外的过滤条件或排序规则,或者增加其他业务需求的接口。
示例:自定义课程过滤
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(detail=False, methods=['get'], url_path='filter-by-price')
def filter_by_price(self, request):
min_price = request.query_params.get('min_price')
max_price = request.query_params.get('max_price')
if min_price and max_price:
courses = Course.objects.filter(price__gte=min_price, price__lte=max_price)
else:
courses = Course.objects.all()
serializer = CourseSerializer(courses, many=True)
return Response(serializer.data)说明:
- 自定义查询:此操作通过 GET 请求,接受查询参数 min_price 和 max_price,然后返回在该价格范围内的课程。
- @action(detail=False):这是一个针对课程集合的操作,而不是单一课程。
访问:
可以通过以下 URL 查询指定价格范围内的课程:
GET /api/courses/filter-by-price/?min_price=50&max_price=2004. 增加权限、认证等自定义设置
@action 装饰器允许你为自定义操作指定特定的权限、认证等配置。这让你能够为不同的自定义操作设置不同的访问控制策略。
示例:自定义权限和认证
from rest_framework.permissions import IsAuthenticated
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
def get_authenticated_courses(self, request):
courses = Course.objects.all()
serializer = CourseSerializer(courses, many=True)
return Response(serializer.data)
说明:
- permission_classes=[IsAuthenticated]:这个操作要求用户已经通过身份验证(即登录后才能访问)。
- @action(detail=False):这个操作是针对整个课程集合的,而不是单个课程。
5. 添加自定义 URL 路径
通过 url_path 参数,你可以为自定义的操作设置一个更友好的 URL 路径,而不必依赖 DRF 默认生成的路径。
class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(detail=False, methods=['get'], url_path='popular-courses')
def popular_courses(self, request):
courses = Course.objects.filter(is_popular=True)
serializer = CourseSerializer(courses, many=True)
return Response(serializer.data)
说明:
- url_path='popular-courses':这个自定义的操作将被暴露为 /api/courses/popular-courses/,而不是默认的操作路径。
总结
@action 装饰器的主要作用是为 ViewSet 添加自定义的操作,使你可以在标准的 CRUD 操作之外,灵活地扩展额外的功能。常见的用途包括:
- 添加自定义的业务逻辑。
- 定义额外的 API 端点,支持特定功能或查询。
- 扩展现有 ViewSet 的功能,比如增加自定义过滤、排序或权限控制。
- 定义针对单个资源或整个资源集合的额外操作。
这些自定义操作使得你可以在 DRF 中轻松实现更加复杂的 API 需求。
评论(0)