如何在django-rest-framework中设置权限,使会话用户只能列出与该用户有外键关系的对象?

2 投票
1 回答
1405 浏览
提问于 2025-04-18 05:15

我有这样的模型:

class TheModel(models.Model):
    name = models.CharField(max_length=10)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)

我想创建一个API视图,列出所有的TheModel对象,其中TheModel.owner等于request.user

我觉得我可以通过重写get_queryset来实现这个功能,但我又觉得应该使用一个自定义的BasePermission。问题是,在列表视图中,似乎BasePermission.has_object_permission并没有在每个对象上运行。运行的只有BasePermission.has_permission。我用这个进行了测试:

class TheModelViewSet(viewsets.ModelViewSet):
    model = TheModel
    permission_classes = [IsOwner]

class IsOwner(permissions.BasePermission):
    def has_permission(self, request, view):
        print("checking has permission for {}".format(request.user))
        return True

    def has_object_permission(self, request, view, obj):
        print("checking permission for {} on {}").format(request.user, obj.user)

        return obj.owner == request.user

打印出来的只有IsOwner.has_permission的内容。

也许我只是想太多了,应该直接使用自定义查询集,而不是使用权限?

1 个回答

6

官方文档建议在这种情况下使用自定义的 get_queryset 方法,我也是这么做的。

权限对象的 has_object_permission 方法只在查看单个对象时才会运行,所以它不适合用来控制列表视图的权限。

简单来说,你不是在试图允许或拒绝访问,而是在过滤结果。直接在数据库层面进行过滤是最快、最简单、也是最安全(出错几率最低)的方法。权限框架的设计只是为了允许或拒绝对某个对象或一组对象的访问,并不是用来过滤特定响应的内容。get_queryset 方法正是用来过滤特定响应内容的,应该这样使用。

撰写回答