77

Django REST Framework を使用して API を作成していますが、クラス ベースのビューを使用するときにメソッドごとにアクセス許可を指定できるかどうか疑問に思っています。

ドキュメントを読む@permission_classesと、パーミッションで保護したいビューの関数に対してデコレータを使用するだけで、関数ベースのビューを作成している場合は非常に簡単です。ただし、クラスで CBV を使用する場合に同じことを行う方法はわかりません。属性を使用APIViewして完全なクラスのアクセス許可を指定するためpermission_classesですが、それはすべてのクラス メソッド ( getpostput... ) に適用されます。 )。

では、API ビューを CBV で記述し、ビュー クラスの各メソッドに異なる権限を指定することは可能ですか?

4

8 に答える 8

65

アクセス許可は View クラス全体に適用されますが、承認の決定では、リクエストの側面 (GET や POST などのメソッドなど) を考慮することができます。

IsAuthenticatedOrReadOnly例として組み込みを参照してください。

SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS']

class IsAuthenticatedOrReadOnly(BasePermission):
    """
    The request is authenticated as a user, or is a read-only request.
    """

    def has_permission(self, request, view):
        if (request.method in SAFE_METHODS or
            request.user and
            request.user.is_authenticated()):
            return True
        return False
于 2013-11-05T08:21:57.363 に答える
54

リクエストメソッドに応じてかなり複雑なアクセス許可ロジックがあるため、CBV を使用しているときに同じ問題に遭遇しました。

私が思いついた解決策は、このページの下部にリストされているサードパーティの「rest_condition」アプリを使用することでした

http://www.django-rest-framework.org/api-guide/permissions

https://github.com/caxap/rest_condition

リクエスト メソッドに応じて各ブランチが実行されるように、パーミッション フロー ロジックを分割しただけです。

from rest_condition import And, Or, Not

class MyClassBasedView(APIView):

    permission_classes = [Or(And(IsReadOnlyRequest, IsAllowedRetrieveThis, IsAllowedRetrieveThat),
                             And(IsPostRequest, IsAllowedToCreateThis, ...),
                             And(IsPutPatchRequest, ...),
                             And(IsDeleteRequest, ...)]

そのため、「Or」はリクエスト メソッドに応じてパーミッションのどのブランチを実行するかを決定し、「And」は受け入れられたリクエスト メソッドに関連するパーミッションをラップするため、パーミッションが付与されるにはすべてがパスする必要があります。各フロー内で「Or」、「And」、および「Not」を組み合わせて、さらに複雑な権限を作成することもできます。

各ブランチを実行するパーミッション クラスは次のようになります。

class IsReadyOnlyRequest(permissions.BasePermission):

    def has_permission(self, request, view):
        return request.method in permissions.SAFE_METHODS


class IsPostRequest(permissions.BasePermission):

    def has_permission(self, request, view):
        return request.method == "POST"


... #You get the idea
于 2014-01-29T10:45:33.550 に答える
3

ViewSets またはsを使用する場合は、ModelViewSet上書きするとうまくいくと思いますget_permissionsdjoser
がこれを処理 する方法を見てください。

例:

class UserViewSet(viewsets.ModelViewSet):
    permission_classes = settings.PERMISSIONS.user  # default

    def get_permissions(self):
        if self.action == "activation":  # per action
            self.permission_classes = settings.PERMISSIONS.activation
        return super().get_permissions()

    @action(["post"], detail=False)  # action
    def activation(self, request, *args, **kwargs):
        pass

    
于 2020-02-08T20:02:44.747 に答える