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

Permission类has_object_permission方法未触发,评论删除权限失效

问题分析与解决方案

核心问题

你的自定义权限方法has_object_permission未执行,是因为重写的destroy方法完全跳过了DRF内置的权限校验流程。DRF的DestroyAPIView默认会通过get_object()获取目标对象,并自动触发check_object_permissions()来调用你的权限校验逻辑,但你直接在destroy里查询并删除评论,完全绕开了这个环节,导致权限检查从未触发。

解决方案

方案1:复用DRF内置校验流程(推荐)

修改视图,通过get_object()获取评论对象,让DRF自动触发权限检查:

class CommentPostApiView(generics.ListCreateAPIView, generics.DestroyAPIView):
    serializer_class = serializers.CommentPostSerializer
    authentication_classes = (TokenAuthentication,)
    permission_classes = [IsAuthenticated, IsCommentOwnerOrPostOwner]

    def get_queryset(self):
        post_id = self.kwargs.get('post_id')
        return models.CommentPost.objects.filter(post__pk=post_id, reply_to_comment__isnull=True)

    # 保留原create方法不变
    @transaction.atomic
    def create(self, request, *args, **kwargs):
        # ... 原create代码 ...

    # 重写destroy方法,复用get_object触发权限校验
    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        comment = self.get_object()
        post_id = comment.post.id
        comment.delete()
        models.PicPost.objects.filter(pk=post_id).update(comments_count=F('comments_count')-1)
        return Response({"detail": "Comment deleted successfully."}, status=status.HTTP_200_OK)

    # 重写get_object,获取要删除的评论并触发权限检查
    def get_object(self):
        comment_id = self.kwargs.get('parent_comment_id')
        try:
            obj = models.CommentPost.objects.select_for_update().get(pk=comment_id)
        except models.CommentPost.DoesNotExist:
            raise ValidationError("This comment does not exist")
        self.check_object_permissions(self.request, obj)
        return obj

方案2:手动触发权限检查

如果不想修改get_object,也可以在自定义destroy方法里手动调用权限校验:

@transaction.atomic
def destroy(self, request, *args, **kwargs):
    comment_id = self.kwargs.get('parent_comment_id')
    try:
        comment = models.CommentPost.objects.select_for_update().get(pk=comment_id)
        # 手动触发权限检查
        self.check_object_permissions(request, comment)
        post_id = comment.post.id
        comment.delete()
        models.PicPost.objects.filter(pk=post_id).update(comments_count=F('comments_count')-1)
    except models.CommentPost.DoesNotExist:
        raise ValidationError("This comment does not exist")
    return Response({"detail": "Comment deleted successfully."}, status=status.HTTP_200_OK)

额外优化点

  1. 修正HTTP状态码:删除成功应返回status.HTTP_200_OK或status.HTTP_204_NO_CONTENT,而非201_CREATED(201是创建成功的状态码)。
  2. 简化视图继承:ListCreateAPIView已继承GenericAPIView,无需重复声明。

验证

修改后,当非评论所有者/非帖子所有者尝试删除评论时,DRF会自动返回403 Forbidden,同时你终端的调试print语句会输出内容,说明has_object_permission已正常执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 18:22:35