对象级权限

Object-level Permissions

我确信这相当简单,但我已经仔细搜索了文档,但我不太清楚如何执行此操作。

我已经扩展了我的 User class 以与其他用户建立两个多对多关系:trainersteammates

如果用户拥有一个对象(由模型上的 user 外键定义),则该用户应该能够 GETPOSTPUTPATCHDELETE。我已经用 ModelViewSet 设置了这些端点。如果用户是所有者的培训师,则他们应该具有相同的权限。如果用户是所有者的队友,他们应该只能 GET

在这些对象的列表视图中,用户应该只能看到他们拥有的对象以及他们是所有者的教练或队友的对象。如果他们尝试访问对象的详细视图,而他们不是所有者的朋友或队友,则应该 return 403。

我按如下方式扩展了 BasePermission 以尝试创建此行为——然后我将其添加到我想要此行为的 ModelViewSet 中。

class TrainerAndOwnerOrTeammate(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        user = request.user
        owner = obj.user

        if user == owner:
            return True

        if user in owner.trainers.all():
            return True

        if user in owner.teammates.all():
            return request.method in permissions.SAFE_METHODS

        return False

由于 REST Framework 文档指定这不是 运行 基于每个对象的列表视图,我覆盖 get_queryset 以按请求用户过滤。

现在的问题是,如果我尝试访问我不应该访问的详细视图,我会收到 404 错误,而不是 403。我明白为什么会这样,但是有办法解决吗?

我认为一种解决方案是删除 get_queryset() 并定义自定义过滤器。 Filter 类 允许您根据正在访问的请求和视图过滤查询集。另一种方法是将您的视图集拆分为多个单独的视图。另一种方法是定义 get_object.

我最终覆盖了 ModelViewSetlist 方法并保留了权限 class。权限 class 处理详细视图和操作,列表方法处理列表视图。