Django rest framework permission_classes of ViewSet 方法

新手上路,请多包涵

我正在使用 Django REST 框架编写一个休息 API,我想用权限保护某些端点。权限类看起来提供了一种优雅的方式来实现这一点。我的问题是我想对不同的重写 ViewSet 方法使用不同的权限类。

 class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def create(self, request, *args, **kwargs):
        return super(UserViewSet, self).create(request, *args, **kwargs)

    @decorators.permission_classes(permissions.IsAdminUser)
    def list(self, request, *args, **kwargs):
        return super(UserViewSet, self).list(request, *args, **kwargs)

在上面的代码中,我也想允许未经身份验证的用户注册(用户创建),但我不想让任何人列出用户,只是为了员工。

文档 中,我看到了使用 permission_classes 装饰器保护 API 视图(不是 ViewSet 方法)的示例,并且我看到了为整个 ViewSet 设置权限类。但它似乎不适用于重写的 ViewSet 方法。有没有办法只将它们用于某些端点?

原文由 fodma1 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 806
2 个回答

我认为没有内置的解决方案。但是您可以通过覆盖 get_permissions 方法来实现:

 from rest_framework.permissions import AllowAny, IsAdminUser

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    permission_classes_by_action = {'create': [AllowAny],
                                    'list': [IsAdminUser]}

    def create(self, request, *args, **kwargs):
        return super(UserViewSet, self).create(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        return super(UserViewSet, self).list(request, *args, **kwargs)

    def get_permissions(self):
        try:
            # return permission_classes depending on `action`
            return [permission() for permission in self.permission_classes_by_action[self.action]]
        except KeyError:
            # action is not set return default permission_classes
            return [permission() for permission in self.permission_classes]

原文由 ilse2005 发布,翻译遵循 CC BY-SA 3.0 许可协议

我创建了一个派生自 @ilse2005 的答案的超类。在后续的所有django视图中都可以继承这个来实现action级别的权限控制。

 class MixedPermissionModelViewSet(viewsets.ModelViewSet):
   '''
   Mixed permission base model allowing for action level
   permission control. Subclasses may define their permissions
   by creating a 'permission_classes_by_action' variable.

   Example:
   permission_classes_by_action = {'list': [AllowAny],
                                   'create': [IsAdminUser]}
   '''

   permission_classes_by_action = {}

   def get_permissions(self):
      try:
        # return permission_classes depending on `action`
        return [permission() for permission in self.permission_classes_by_action[self.action]]
      except KeyError:
        # action is not set return default permission_classes
        return [permission() for permission in self.permission_classes]

原文由 Robert Christopher 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题