基于方法的Django Rest框架视图集权限

3

所以我正在用DRF写我的第一个项目,但是在设置ViewSets权限时遇到了一些问题。我已经使用djangorestframework-jwt实现了认证。目前,我定义了几个不同的ViewSets。我想做的是允许模型对象的所有者对该对象进行任何更改,但是防止其他人(除管理员外)查看该对象。基本上,我需要一种将权限类应用于特定方法的方法,以允许仅管理员查看“列表”,仅所有者可以“更新、删除等”,而认证用户则可以“创建”对象。目前我的代码大致如下:

class LinkViewSet(viewsets.ModelViewSet):
   queryset = Link.objects.all()
   serializer_class = LinkSerializer

使用模型

class Link(models.Model):
   name = models.CharField(max_length=200)
   url = models.URLField()
   # another model with a OneToMany relationship
   section = models.ForeignKey('homepage.LinkSection', related_name='links', on_delete=models.CASCADE
   owner = models.ForeignKey('homepage.UserProfile'), related_name='links', on_delete=models.CASCADE)

我想要应用的权限类

class IsOwner(permissions.BasePermission):
   def has_object_permissions(self, request, view, obj):
      return obj.owner == request.user.userprofile

我相信通过编写完全自定义的视图可以实现这一点,但我有一种直觉认为有更简单的方法来完成这个任务,特别是因为这基本上是我完成API所需做的最后一件事。感谢任何帮助,并让我知道是否需要更多信息。


你可以在 has_object_permission() 中像 DjangoModelPermissions 一样检查 request.method - kichik
非常感谢,我已经弄清楚了,我会在帖子中添加一个答案。 - Eric Groom
1个回答

7

我能够通过检查视图中使用的操作来创建一个权限类,具体方法如下:

class IsOwner(permissions.BasePermission):
'''
Custom permission to only give the owner of the object access
'''
message = 'You must be the owner of this object'

def has_permission(self, request, view):
    if view.action == 'list' and not request.user.is_staff:
        print('has_permission false')
        return False
    else:
        print('has_permission true')
        return True

def has_object_permission(self, request, view, obj):
    print('enter has_object_permission')
    # only allow the owner to make changes
    user = self.get_user_for_obj(obj)
    print(f'user: {user.username}')
    if request.user.is_staff:
        print('has_object_permission true: staff')
        return True
    elif view.action == 'create':
        print('has_object_permission true: create')
        return True
    elif user == request.user:
        print('has_object_permission true: owner')
        return True # in practice, an editor will have a profile
    else:
        print('has_object_permission false')
        return False

def get_user_for_obj(self, obj):
    model = type(obj)
    if model is models.UserProfile:
        return obj.user
    else:
        return obj.owner.user

get_user_for_obj是我实现的一个帮助方法,因为我的模型在获取用户实例方面不一致。您不希望使has_permission过于严格,因为只有在has_permission返回True或未被覆盖时,has_object_permission才会运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接