Django rest framework 视图集上的详细信息路由不符合对象级权限
这是我的视图集:Django rest framework 视图集上的详细信息路由不符合对象级权限,django-rest-framework,Django Rest Framework,这是我的视图集: class PageViewSet(viewsets.ModelViewSet): queryset = Page.objects.all() serializer_class = PageSerializer permission_classes = (IsAuthenticated, IsOwnerOrReadOnly,) def perform_create(self, serializer): serializer.sa
class PageViewSet(viewsets.ModelViewSet):
queryset = Page.objects.all()
serializer_class = PageSerializer
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user, location=self.request.user.userextended.location)
@detail_route(methods=['post'])
def add(self, request, pk=None):
try:
page = Page.objects.get(pk=pk)
except:
content = {'Page': ['The page you are trying to add no longer exists.']}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
page.users.add(request.user)
return Response(status=status.HTTP_204_NO_CONTENT)
这是我的IsownerReadOnly
权限:
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Allow only the owner (and admin) of the object to make changes (i.e.
do PUT, PATCH, DELETE and POST requests. A user is an
owner of an object if the object has an attribute
called owner and owner is == request.user. If the
object is a User object or if the object does not have
an owner attribute, then return object == request.user.
"""
def has_permission(self, request, view):
print('In permission')
return True
def has_object_permission(self, request, view, obj):
print('In object level permission')
if request.method in permissions.SAFE_METHODS:
return True
if request.user.is_staff:
return True
try:
return obj.owner == request.user
except: # if obj does not have an owner property (e.g. users don't
# have owner properties).
return obj == request.user
问题是,即使我不是页面的所有者,我也可以作为经过身份验证的用户发布到添加详细信息。当我执行post请求时,它只在权限中打印两次,而从不在对象级权限中打印。我的问题是,既然它是一个detail\u路由
,并且显然使用了{lookup}
对象(请参见此处显示它使用的是对象:),为什么权限类中的has\u object\u permission()
函数没有被调用?为什么只有常规的具有\u权限()
函数被调用
我希望有人能链接到一个文档,以验证即使对于detail\u route
,也只有有权调用
编辑:这不是的副本,因为我使用的是从GenericAPIView继承的ModelViewSet(如文档中所述:)。请参阅。虽然存在一些差异,但要点是相同的:检查对象\u权限
未被调用
尽管您是从ModelViewSet
继承的,但您没有在add
方法中使用其get\u对象
来检索页面。是get\u object
调用check\u object\u permissions
(不是路由器)进行检索、更新等操作,因此显然不会调用它
要修复它,请执行以下操作:
class PageViewSet(viewsets.ModelViewSet):
# ...
@detail_route(methods=['post'])
def add(self, request, pk=None):
page = self.get_object()
page.users.add(request.user)
return Response(status=status.HTTP_204_NO_CONTENT)
或者只做self。检查\u object\u权限(第页)
您自己在实现中的某个地方 @Ivan这不是你链接到的帖子的副本,因为我使用的是从GenericAPIView继承的ModelViewSet(我也编辑了我的帖子以添加此信息)。这一点与在接受的答案中相同,由你在添加中调用检查对象权限@Ivan。答案是:“对象的权限检查由DRF在APIView.check_object_permissions方法中完成。由于您不使用GenericAPIView,因此您可以定义自己的get_object方法,并且您必须自己调用check_object_permissions。”但是,我确实使用它(我从中继承),并且用于所有其他PageViewSet请求(PUT、PATCH和DELETE),check\u object\u permissions
的IsownerReadOnly
被调用得非常好。只是它不适用于我的详细路由功能。想知道文档中说的detail\u route
是否不使用对象级权限?这就是我想说的:检查权限的不是路由器。Wh如果您定义了一个要发送到的操作,则您可以调用检查对象权限
,如果您没有使用获取对象
。我在您的添加中没有看到它。我将发布完整的答案。