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

DRF中Extra Action ViewSet无法识别对象权限问题

问题原因

DRF 的权限检查逻辑是先执行 has_permission,通过后才会触发 has_object_permission。而 has_object_permission 只有在视图成功获取到对应的模型实例(obj)时才会被调用。

你的 block 方法里没有调用 self.get_object() 来获取目标对象,而是直接用 pk 调用了自定义的 _block_page 方法。DRF 无法自动拿到要检查的对象,自然不会执行 IsModeratorOfThePageOwner 里的 has_object_permission 方法,导致权限校验完全失效。另外,BasePermission 基类的 has_permission 默认返回 True,所以权限检查直接通过了。

解决方案

有两种可行的修复方式:

方案一:在 Action 方法中手动获取对象

在 block 方法开头调用 get_object(),触发 DRF 的对象级权限检查:

@action(
    detail=True,
    methods=["patch"],
    permission_classes=[IsModeratorOfThePageOwner]
)
def block(self, request, pk=None):
    obj = self.get_object()  # 这一步会触发 has_object_permission 检查
    self._block_page(pk)
    return Response(
        data={"detail": "Successfully blocked."},
        status=status.HTTP_200_OK,
    )

方案二:给权限类补充 has_permission 方法

在权限类中实现 has_permission,手动获取对象并执行校验逻辑:

class IsModeratorOfThePageOwner(BasePermission):
    def has_permission(self, request, view):
        # 先校验用户角色
        if not request.user_data or request.user_data.get("role") != "Moderator":
            return False
        # 获取目标对象并校验组ID匹配
        obj = view.get_object()
        return obj.owner_group_id == request.user_data.get("group_id")
    
    def has_object_permission(self, request, view, obj):
        # 保留原方法,兼容其他需要对象级校验的场景
        return bool(
            request.user_data
            and request.user_data.get("role") == "Moderator"
            and obj.owner_group_id == request.user_data.get("group_id")
        )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:43:14