因此,我浏览了关于同一主题的类似问题,并且 我认为 我遵循为has_object_permission
指定的所有规则。
这就是我的设置。
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
'users.permissions.CanAccessData', # this is my custom class
],
.
.
.
}
这是我的权限等级
class CanAccessData(permissions.BasePermission):
message = 'You do not have permission to perform this action.'
def has_permission(self, request, view):
print "has_permission`"
return True
def has_object_permission(self, request, view, obj):
print "has_object_permission"
return False
这是我的视图结构:
class CompleteList(generics.ListCreateAPIView):
permission_classes = (CanAccessData,)
serializer_class = SomeSerializer
model = Some
filter_backends = (filters.OrderingFilter, filters.SearchFilter)
ordering_fields = (tuple of Some fields)
search_fields = ordering_fields
ordering = ('-create_date')
仍然,has_object_permission
未被调用,has_permission
被调用。
谢谢。
答案 0 :(得分:0)
列表视图未调用has_object_permission
。 documentation说:
还请注意,通用视图将仅检查对象级权限以获取检索单个模型实例的视图。如果需要列表视图的对象级过滤,则需要分别过滤查询集。有关更多详细信息,请参见过滤文档。
答案 1 :(得分:0)
我遇到了同样的问题。列出对象时,永远不会调用has_object_permission
函数。
即使以下方法不是最有效的解决方案,您也可以按如下所示在视图中覆盖list
方法,这就是我为我解决的方法:
from typing import List
import rest_framework.permissions as drf_permissions
def list(self, request, *args, **kwargs):
# base query set
queryset: QuerySet = self.filter_queryset(self.get_queryset())
# check object permissions for each object individually
valid_pks: List[int] = [] # # storage for keys of valid objects
permissions: List[drf_permissions.BasePermission] = self.get_permissions()
for obj in queryset:
for permission in permissions:
if permission.has_object_permission(request, self, obj):
valid_pks.append(obj.pk)
# remove not valid objects from the queryset
queryset = queryset.filter(pk__in=valid_pks)
# ... business as usual (original code)
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
这基本上是原始的实现,除了它预取相关对象并逐个检查权限。
但是,在不必重写get_queryset()
方法以某种方式重新发明has_object_permission
逻辑的意义上,这可能是DRY。但是它也很慢,因为它两次获取对象。您可以通过使用已经预取的对象而不是过滤查询集来改善这种情况。