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

