Django-rest-framework: Разрешения объекта не проверяются на настраиваемых маршрутах набора представлений

Созданный на 23 мая 2016  ·  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)),
]

сделать запрос GET к / api / mymodel / 123 / custom /

Ожидаемое поведение

has_object_permission () следует вызывать с MyModel.objects.get(pk=123) качестве объекта.

Фактическое поведение

запрос к настраиваемому маршруту в форме / api / mymodel / 123 / custom / вызовет has_permission () в MyPermissions, но не has_object_permission (), даже если это подробный маршрут.

Documentation

Самый полезный комментарий

Нам нужно задокументировать тот факт, что вы получите вызов has_object_permission только если вы вызовете get_object .

Все 4 Комментарий

Нам нужно задокументировать тот факт, что вы получите вызов 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/ #object -level -permissions

Закрытие этого, но, как уже отмечалось, могут быть рассмотрены конкретные изменения / дополнения.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги