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如果您定义了一个要发送到的操作,则您可以调用
检查对象权限
,如果您没有使用
获取对象
。我在您的
添加中没有看到它。我将发布完整的答案。