如何在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
相关产品推荐
相关产品推荐

