django rest框架对象权限

时间:2017-05-18 16:11:47

标签: django django-rest-framework

我似乎没有触发has_object_permission功能。

class MyPermission(DefaultPermission):
    def has_permission(self, request, view):
        return request.user.is_superuser

    def has_object_permission(self, request, view, obj):
        import pdb;pdb.set_trace()
        return request.user == obj.submitter

转到mydomain.com/api/mymodel/100,应该考虑访问该对象,对吗?我在这里查看对象100。为什么我的trace()没有被接听?

视图

class MyModelViewSet(viewsets.ModelViewSet):
    serializer_class = MyModelSerializer
    permission_classes = (MyPermission,)

    def get_queryset(self):
        queryset = MyModel.objects.all()
        return queryset

2 个答案:

答案 0 :(得分:2)

在DRF通用视图中,check_permissions(request)始终在每个请求中被调用,因为它位于调度方法中。

check_permissions方法从权限类中收集所有权限并检查每个权限。如果任何权限返回false,则该方法会引发异常。

因此,如果您的has_permission方法返回false,则不会调用has_object_permission

check_object_permissions(request, obj)在每个权限类上调用has_object_permission方法。它在get_object方法内部调用。

因此规则是,如果所有权限类的has_permission返回true,则仅检查has_object_permission

class MyPermission(DefaultPermission):

    def has_permission(self, request, view):
        # check if the request is for a single object
        if view.lookup_url_kwarg in view.kwargs:
            return True
        return request.user.is_superuser

    def has_object_permission(self, request, view, obj):
        import pdb;pdb.set_trace()
        return request.user == obj.submitter

答案 1 :(得分:1)

权限不会起作用,因为check_object_permissions方法仅在get_object函数中调用。所以你应该在你的视图中调用该函数:

    class MyViewSet(ModelViewSet):
        queryset = MyModel.objects.all()
        ....
        permission_classes = (MyPermission, )


        @detail_route(methods=['GET', ])
        def custom(self, request, pk=None):
            my_obj = self.get_object() # do this and your permissions shall be checked
            return Response('whatever')

或者您可以直接在装饰器中添加权限,

实施例

def payload = '''<logs>
<log>
  <text>LOG 1</text>
  <timestamp>2017-05-18T16:20:00.000</timestamp>
</log>
<log>
  <text>LOG 2</text>
  <timestamp>2017-05-18T16:20:00.000</timestamp>
</log>
</logs>'''

def logs = new XmlParser().parseText(payload) 
def result = logs.log.collect {  
    def sw = new StringWriter()
    def pw = new PrintWriter(sw)
    new XmlNodePrinter(pw).print(it)
    sw.toString().replaceAll('\\s', '')
}

来自docs(django-rest-framework)

  

注意:只有在已经通过了视图级别has_permission检查时,才会调用实例级别的has_object_permission方法。另请注意,为了运行实例级别检查,视图代码应显式调用.check_object_permissions(request,obj)。如果您使用的是通用视图,则默认情况下将为您处理。