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()は呼び出しません。
get_object
を呼び出した場合にのみ、 has_object_permission
呼び出されるという事実を文書化する必要があります。
これは直感に反しているようです。 / 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/で十分だと思い
これを締めくくりますが、前述のように、特定の言い換え/追加を検討することができます。
最も参考になるコメント
get_object
を呼び出した場合にのみ、has_object_permission
呼び出されるという事実を文書化する必要があります。