【问题标题】:DRF Viewset remove permission for detail routeDRF Viewset 删除详细路线的权限
【发布时间】:2019-03-03 18:33:58
【问题描述】:

我有一个基本的视图集:

class UsersViewSet(viewsets.ModelViewSet):
    permission_classes = (OnlyStaff,)
    queryset = User.objects.all()
    serializer_class = UserSerializer

它绑定到/api/users/ 端点。我想创建一个用户个人资料页面,所以我只需要一个特定的用户,所以我可以从/api/users/<id>/ 检索它,但问题是我希望任何人都可以使用/api/users/<id>/,但/api/users/ 保留它权限OnlyStaff,所以没有人可以访问完整的用户列表。

注意:也许这不是一个很好的实现,因为任何人都可以强制增加 id 的数据,但我愿意将其从 <id> 更改为 <slug>

如何删除详细路由的权限?

提前致谢。

【问题讨论】:

    标签: django django-rest-framework django-permissions


    【解决方案1】:

    重写 get_permissions() 方法如下

    from rest_framework.permissions import AllowAny
    
    
    class UsersViewSet(viewsets.ModelViewSet):
        permission_classes = (OnlyStaff,)
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
        def get_permissions(self):
            if self.action == 'retrieve':
                return [AllowAny(), ]        
            return super(UsersViewSet, self).get_permissions()

    【讨论】:

    • 再次感谢。所以覆盖特定方法权限的有效方法是覆盖get_permissions(),而不是属性permission_classes
    【解决方案2】:

    如果您发布权限类会有所帮助。

    但是根据您发布的内容,似乎只有员工用户才能访问绑定到该视图集的端点。这意味着没有其他用户类型/角色可以访问这些端点。

    解决您的问题,您似乎想设置 IsOwnerOrStaffOrReadOnly 权限并覆盖 ModelViewSet 的列表路由功能并替换 permission_classes 然后调用 super

    class UsersViewSet(viewsets.ModelViewSet):
        permission_classes = (IsOwnerOrStaffOrReadOnly,)
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    def list(self, request, *arg, **kwargs):
       self.permission_classes = (OnlyStaffCanReadList,)
       super(UsersViewSet, self).list(request, *args, **kwargs)  // python3 super().list(request, *args, **kwargs)
    

    是 Owner 对象权限类

    class IsOwnerOrStaffOrReadOnly(permissions.BasePermission):
    
        def has_object_permission(self, request, view, obj):
            # Read permissions are allowed to any request,
            # so we'll always allow GET, HEAD or OPTIONS requests.
            if request.method in permissions.SAFE_METHODS:
                return True
    
            if request.user.role == 'staff': 
               return True
            # Instance must have an attribute named `owner`.
            return obj.owner == request.user
    

    只有员工可以读取权限类

    class OnlyStaffCanReadList(permissions.BasePermission):
    
        def has_object_permission(self, request, view, obj):
            if request.user.role == 'Staff': 
               return True
            else:
               return False
    

    根据 cmets 的规定,您的用户模型必须具有所有者角色。如果您使用的是 django 用户模型,则可以进行 obj.id == request.user.id 比较

    【讨论】:

    • 覆盖list() 方法不起作用,它不会被执行。 IsOwnerOrStaffOrReadOnly 在两个端点中执行。
    • @yierstem 很奇怪。我做了一个 jdoodle 来验证继承类中元组的覆盖,以验证它应该是这种情况。查看 jdoodle.com/a/GQg。在进一步查看之后,似乎在单条路线上覆盖烫发可能存在问题。看看这个。 stackoverflow.com/questions/25283797/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 2015-02-12
    • 2021-08-07
    • 1970-01-01
    • 2019-12-07
    相关资源
    最近更新 更多