如何在django-rest-framework中设置权限,使会话用户只能列出与该用户有外键关系的对象?
我有这样的模型:
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
方法正是用来过滤特定响应内容的,应该这样使用。