django-rest-framework:在ViewSet更新方法中添加其他权限

时间:2014-08-13 10:26:59

标签: python django django-rest-framework

我有以下代码:

class UsersViewSet(viewsets.ModelViewSet):
    model = Users
    permission_classes = (IsAuthenticated,)

    def update(self, request, *args, **kwargs):
        return super(UsersViewSet, self).update(request, *args, **kwargs)

问题是:

  • 如何仅为更新方法添加其他权限? (需要获得isAuthenticated + Permission)
  • 仅为更新方法覆盖权限? (只需获得没有isAuthenticated的权限) viewset中的其他方法应具有IsAuthenticated权限

我可以使用装饰器制作吗?还是其他什么?

想得到类似的东西:

@permission_classes((IsAuthenticated, AdditionalPermission ))
def update:
    pass

但是,如果我编写此代码,则不会通过请求检查第二个权限

5 个答案:

答案 0 :(得分:13)

稍后编辑

由于看起来DRF装饰员不能真正起作用(至少不适合我),这是我能想到的最好的解决方案:

def get_permissions(self):
    # Your logic should be all here
    if self.request.method == 'GET':
        self.permission_classes = [DummyPermission, ]
    else:
        self.permission_classes = [IsAuthenticated, ]

    return super(UsersViewSet, self).get_permissions()

这实际上适用于您提出的两种情况,但需要更多工作。但是,我已经对它进行了测试,并完成了这项任务。

以下的原始答案

文档中存在一个小错误,您应该向装饰器(而不是元组)发送一个列表。所以它应该是这样的:

@permission_classes([IsAuthenticated, AdditionalPermission, ])
def update:
    pass

回答你的问题:

如何仅为更新方法添加其他权限?

首先,您应该知道DRF首先检查全局权限(来自设置文件的权限),然后查看权限(在 permission_classes 中声明 - 如果存在,它们将覆盖全局权限)并且仅在此之后获得方法权限(使用装饰器 @permission_classes 声明)。所以另外一种方法就是这样:

@permission_classes([AdditionalPermission, ])
def update:
    pass

由于已经在整个视图中设置了 ISAuthenticated ,因此将始终在任何其他权限之前对其进行检查。

仅为更新方法覆盖权限?

嗯,这很难(呃),但并非不可能。你可以:

  • 设置每个方法的权限并将其从类中删除
  • 修改您的AdditionalPermission类,以便在方法不是 update 的情况下检查用户身份验证。
祝你好运。

答案 1 :(得分:7)

您还可以在 get_permissions()方法中指定特定方法的权限:

class MyViewSet(viewsets.ModelViewSet):

    def get_permissions(self):
        if self.action in ('update', 'other_viewset_method'):
            self.permission_classes = [permissions.CustomPermissions,]
        return super(self.__class__, self).get_permissions()

答案 2 :(得分:2)

@permission_classes不适用于基于类的视图。我尝试了@detail_route(permission_classes =(permissions.CustomPermissions,))来获取更新视图功能,但仍无效。

所以,我的解决方案是:

 class MyViewSet(viewsets.ModelViewSet):

    def update(self, request, *args, **kwargs):
        self.methods=('put',)
        self.permission_classes = (permissions.CustomPermissions,)
        return super(self.__class__, self).update(request, *args, **kwargs)

试一试。我的drf是v3.1.1

答案 3 :(得分:0)

是的,您可以添加注释 有关更多信息,请参阅此链接:

https://docs.djangoproject.com/en/1.6/topics/auth/default/#django.contrib.auth.decorators.permission_required

答案 4 :(得分:0)

对我来说,get_permissions起作用了,但是事实证明,即使将权限设置为AllowAny,如果在请求rest框架的标头中发送Authorization,也会抛出错误。如果您要同时使用授权和AllowAny,则必须考虑到这一点。