我似乎没有触发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
答案 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', '')
}
注意:只有在已经通过了视图级别has_permission检查时,才会调用实例级别的has_object_permission方法。另请注意,为了运行实例级别检查,视图代码应显式调用.check_object_permissions(request,obj)。如果您使用的是通用视图,则默认情况下将为您处理。