diadia

興味があることをやってみる。自分のメモを残しておきます。

APIViewのpermission_classesはどんな仕組みで動いているのか

APIViewのプロパティは以下の通り。

# APIViewのプロパティ  

class APIView(View):

    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES #コイツ
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    # Allow dependency injection of other settings to make testing easier.
    settings = api_settings

    schema = DefaultSchema()

次にpermission_classesを使っているメソッドは何があるか??
それはget_permissionsだった。このメソッドはpermisson_classをインスタンス化したリストを作成する役割である。

# https://github.com/encode/django-rest-framework/blob/3db88778893579e1d7609b584ef35409c8aa5a22/rest_framework/views.py#L274

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        return [permission() for permission in self.permission_classes]

じゃあ、このget_permissionsメソッドはどの文脈で使われているかということが次の疑問になる。
それは以下の通りcheck_permissionsとcheck_object_permissionsメソッドで使われていることが判明した。

    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        for permission in self.get_permissions():
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )

    def check_object_permissions(self, request, obj):
        """
        Check if the request should be permitted for a given object.
        Raises an appropriate exception if the request is not permitted.
        """
        for permission in self.get_permissions():
            if not permission.has_object_permission(request, self, obj):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )

こレラのメソッドはパーミッションがない場合にパーミッション拒否のメソッドが実行される。そういう意味で、permission.has_permission()メソッドがパーミッションのチェックとなっている。 このメソッドはpermissons.pyの各クラスメソッドに規定されている。

https://github.com/encode/django-rest-framework/blob/d635bc9c71b6cf84d137a68610ae2e628f8b62b3/rest_framework/permissions.py