Django-rest-framework: 不检查自定义视图集路由上的对象权限

创建于 2016-05-23  ·  4评论  ·  资料来源: encode/django-rest-framework

重现步骤

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    authentication_classes = (MyAuth, )
    permission_classes = (MyPermissions, )

    @detail_route(methods=["GET", ])
    def custom(self, request, pk=None):
        return Response('whatever')

from rest_framework import routers
router = routers.SimpleRouter() 
router.register('mymodel', MyViewSet)
urlpatterns = [
    url(r'^api/', include(router.urls)),
]

向 /api/mymodel/123/custom/ 发出 GET 请求

预期行为

has_object_permission() 应该用MyModel.objects.get(pk=123)作为对象来调用。

实际行为

以 /api/mymodel/123/custom/ 形式对自定义路由的请求将调用 MyPermissions 中的 has_permission(),但不会调用 has_object_permission(),即使它是详细路由。

Documentation

最有用的评论

我们需要记录这样一个事实,即只有在调用get_object才会调用has_object_permission get_object

所有4条评论

我们需要记录这样一个事实,即只有在调用get_object才会调用has_object_permission get_object

这似乎违反直觉。 像 /api/object/123/method/ 这样的调用通常用于调用 ID 为 123 的对象实例上的某些方法,并且检查对象权限似乎是一种预期行为。 否则,每次有人制作自定义详细路线时,他们都必须检索对象,手动检查权限并继续。 在这一点上,调用 has_object_permission() 无论如何都没有意义。 因此,在使用对象级别权限的每种情况下,都必须使用一些像这样的样板

class CustomPermission(BasePermission):
    def has_permission(self, request, view):
        """we need to do all permission checking here, since has_object_permission() is not guaranteed to be called"""
        if 'pk' in view.kwargs and view.kwargs['pk']:
            obj = view.get_queryset()[0]
            # check object permissions here
        else:
            # check model permissions here

    def has_object_permission(self, request, view, obj):
        """ nothing to do here, we already checked everything, so ignore """
        return True

我想我现在明白了。 如果我在自定义路由中调用 get_object(),则会调用 has_object_permission()。 似乎仍然违反直觉,但至少有一个明确的解决方案。

我很乐意考虑对文档的具体拉取请求,但就目前而言,我认为我们在http://www.django-rest-framework.org/api-guide/permissions/ 中已经足够了

结束这个,但如前所述,可以考虑特定的改写/添加。

此页面是否有帮助?
0 / 5 - 0 等级