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 (), даже если это подробный маршрут.
Нам нужно задокументировать тот факт, что вы получите вызов 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
Закрытие этого, но, как уже отмечалось, могут быть рассмотрены конкретные изменения / дополнения.
Самый полезный комментарий
Нам нужно задокументировать тот факт, что вы получите вызов
has_object_permission
только если вы вызоветеget_object
.