You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST Framework generics视图中配置action装饰器及URL?

解决方案:在DRF通用视图中实现点赞接口

首先明确:@action装饰器是DRF为ViewSet类设计的,它会自动和路由系统配合生成子路由,但RetrieveUpdateDestroyAPIView属于通用视图类,并非ViewSet体系,所以直接给它的方法加@action不会生效,直接指向类方法也无法处理请求(因为视图类需要实例化后处理请求)。

以下是两种可行的实现方案:

方案一:改用ModelViewSet(推荐)

如果业务允许,将AnswerDetailView改为继承ModelViewSet,这样可以直接利用@action装饰器自动生成目标URL,同时保留原有的查询、更新、删除功能:

视图代码

from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Answer
from .serializers import AnswerSerializer

class AnswerViewSet(viewsets.ModelViewSet):
    queryset = Answer.objects.all()
    serializer_class = AnswerSerializer
    lookup_field = "pk"  # 默认就是pk,可省略

    # 实现点赞动作,detail=True表示需要传入pk参数
    @action(detail=True, methods=["post"])
    def like(self, request, pk=None):
        answer = self.get_object()
        # 这里替换成你的点赞逻辑
        answer.likes += 1
        answer.save()
        return Response({"status": "liked", "likes_count": answer.likes})

URL配置

使用DRF的路由自动生成:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register(r"answers", views.AnswerViewSet)

urlpatterns = [
    path("", include(router.urls)),
]

这样会自动生成符合需求的URL:answers/<int:pk>/like/,同时原有的answers/<int:pk>/等CRUD路由也会自动生成。

方案二:保留通用视图,手动配置点赞接口

如果不想修改原有视图的继承关系,可以单独实现点赞视图,或者复用原视图类的方法手动绑定路由:

方式1:单独写点赞视图类

# 视图代码
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Answer
from .serializers import AnswerSerializer

class AnswerLikeView(APIView):
    def post(self, request, pk):
        try:
            answer = Answer.objects.get(pk=pk)
            # 点赞逻辑
            answer.likes += 1
            answer.save()
            serializer = AnswerSerializer(answer)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Answer.DoesNotExist:
            return Response({"error": "回答不存在"}, status=status.HTTP_404_NOT_FOUND)
# URL配置
from django.urls import path
from . import views

urlpatterns = [
    # 原有的详情视图
    path("answers/<int:pk>/", views.AnswerDetailView.as_view(), name="answer-detail"),
    # 点赞视图
    path("answers/<int:pk>/like/", views.AnswerLikeView.as_view(), name="answer-like"),
]

方式2:复用原视图类的方法

在原AnswerDetailView中添加点赞方法,通过as_view()手动绑定动作:

# 视图代码
from rest_framework.generics import RetrieveUpdateDestroyAPIView
from rest_framework.response import Response
from .models import Answer
from .serializers import AnswerSerializer

class AnswerDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Answer.objects.all()
    serializer_class = AnswerSerializer

    def like(self, request, *args, **kwargs):
        answer = self.get_object()
        # 点赞逻辑
        answer.likes += 1
        answer.save()
        return Response({"status": "liked", "likes_count": answer.likes})
# URL配置
path("answers/<int:pk>/like/", views.AnswerDetailView.as_view(actions={"post": "like"}), name="answer-like"),

内容的提问来源于stack exchange,提问作者eurus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 17:15:33