Django REST Framework viewset per-action permissions

前端 未结 5 986
忘掉有多难
忘掉有多难 2020-12-13 00:38

Is there a best practice to assign a different permission to each action of a given APIView or ViewSet?

Let\'s suppose I defined some permis

5条回答
  •  执念已碎
    2020-12-13 00:49

    In DRF documentation,

    Note: The instance-level has_object_permission method will only be called if the view-level has_permission checks have already passed

    Let's assume following permission about user object

    • List : staff only
    • Create : anyone
    • Retrieve : own self or staff
    • Update, Partial update : own self or staff
    • Destroy : staff only

    permissons.py

    from rest_framework import permissions
    
    class UserPermission(permissions.BasePermission):
    
        def has_permission(self, request, view):
            if view.action == 'list':
                return request.user.is_authenticated() and request.user.is_admin
            elif view.action == 'create':
                return True
            elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
                return True
            else:
                return False
    
        def has_object_permission(self, request, view, obj):
            # Deny actions on objects if the user is not authenticated
            if not request.user.is_authenticated():
                return False
    
            if view.action == 'retrieve':
                return obj == request.user or request.user.is_admin
            elif view.action in ['update', 'partial_update']:
                return obj == request.user or request.user.is_admin
            elif view.action == 'destroy':
                return request.user.is_admin
            else:
                return False
    

    views.py

    from .models import User
    from .permissions import UserPermission
    from .serializers import UserSerializer
    from rest_framework import viewsets
    
    
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        permission_classes = (UserPermission,)
    

    EDIT

    For Django 2.0 replace is_authenticated() with is_authenticated. The method has been turned into an attribute.

提交回复
热议问题