Django DRF @action 裝飾器

侬侬发發表於2024-07-17

@action 裝飾器在Django REST Framework (DRF) 中非常有用,它可以幫助你在ViewSet中建立自定義的動作,而不僅僅是依賴標準的CRUD操作(Create, Read, Update, Delete)。以下是 @action 裝飾器的一些常見用法:

1. 建立自定義集合動作

detail=False 表示這個動作是針對整個集合的。例如,你可以建立一個獲取所有使用者統計資訊的動作:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=False, methods=['get'])
    def statistics(self, request):
        user_count = User.objects.count()
        return Response({'user_count': user_count})

2. 建立自定義例項動作

detail=True 表示這個動作是針對單個例項的。例如,你可以建立一個標記使用者為活躍的動作:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=True, methods=['post'])
    def activate(self, request, pk=None):
        user = self.get_object()
        user.is_active = True
        user.save()
        return Response({'status': 'user activated'})

3. 支援多種HTTP方法

你可以指定動作支援的HTTP方法。例如,你可以建立一個既支援GET又支援POST的動作:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=False, methods=['get', 'post'])
    def custom_action(self, request):
        if request.method == 'GET':
            return Response({'message': 'This is a GET request'})
        elif request.method == 'POST':
            data = request.data
            return Response({'message': 'This is a POST request', 'data': data})

4. 指定URL路徑和名稱

你可以指定自定義動作的URL路徑和名稱。例如:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=True, methods=['post'], url_path='set-password', url_name='set_password')
    def set_password(self, request, pk=None):
        user = self.get_object()
        new_password = request.data.get('password')
        user.set_password(new_password)
        user.save()
        return Response({'status': 'password set'})

5. 使用許可權和認證

你可以為自定義動作設定許可權和認證。例如:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=True, methods=['get'], permission_classes=[IsAuthenticated])
    def profile(self, request, pk=None):
        user = self.get_object()
        serializer = self.get_serializer(user)
        return Response(serializer.data)

6. 返回自定義響應

你可以在自定義動作中返回任何型別的響應。例如,檔案下載、重定向等:

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import viewsets
from django.http import FileResponse

class DocumentViewSet(viewsets.ModelViewSet):
    queryset = Document.objects.all()
    serializer_class = DocumentSerializer

    @action(detail=True, methods=['get'])
    def download(self, request, pk=None):
        document = self.get_object()
        file_handle = document.file.open()
        response = FileResponse(file_handle, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="{document.filename}"'
        return response

總結

@action 裝飾器為Django REST Framework中的ViewSet提供了極大的靈活性,允許你在標準的CRUD操作之外新增自定義邏輯和功能。這使得你能夠建立更加豐富和複雜的API端點,滿足具體的業務需求。

相關文章