DRF中的action装饰器介绍

在 Django REST Framework (DRF) 中,@action 装饰器主要用于为 ViewSet 添加自定义的操作。它使得你能够定义超出标准 CRUD 操作(listcreateretrieveupdatedestroy)之外的额外行为。这些自定义操作通常用来处理一些特殊的业务逻辑,或是某些针对特定资源的额外功能。

主要用途

  1. 添加自定义的业务逻辑
  2. 定义额外的 API 端点
  3. 增强标准视图集(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,你可以为 ModelViewSetViewSet 添加额外的逻辑,扩展标准的 listretrievecreateupdatedestroy 等操作。例如,你可以添加一个额外的过滤条件或排序规则,或者增加其他业务需求的接口。

示例:自定义课程过滤

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=200

4. 增加权限、认证等自定义设置

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