Как применить разрешения на perform_create в ViewSet DRF

Это мой набор представлений:

class MyViewSet(ModelViewSet):
    serializer_class = MySerializer
    queryset = MyClass.objects.all()

   def get_serializer_class(self):
        if self.request.user.is_superuser:
            return self.serializer_class 

        return serializers.MyUserSerializer   

    def perform_create(self, serializer):
        employee = models.Employee.objects.get(user=self.request.user)
        serializer.save(employee=employee)

Я хочу применить разрешение перед выполнением функции perform_create, эта функция perform_create() должна вызываться только в том случае, если вошедший в систему пользователь не является суперпользователем. Если вошедший в систему пользователь является суперпользователем, должна быть вызвана стандартная функция perform_create.

Как это сделать?

Попробуйте эту логику

def perform_create(self, serializer):
  self.request.data.get("title", None)  # read data from request
  if self.request.user.is_authenticated and not self.request.user.is_superuser:
      instance = serializer.save(author=self.request.user)
  else:
      instance = serializer.save() 

Вы можете использовать permission_classes в своем классе Viewset

from rest_framework.permissions import IsAuthenticated
class MyViewSet(ModelViewSet):
    permission_classes = (IsAuthenticated,)
    serializer_class = MySerializer
    queryset = MyClass.objects.all()

    ...

Попробуйте следующим образом:

class MyViewSet(ModelViewSet):
    serializer_class = MySerializer
    queryset = MyClass.objects.all()

    def get_serializer_class(self):
        if self.request.user.is_superuser:
            return self.serializer_class 

        return serializers.MyUserSerializer   

    def perform_create(self, serializer):
        employee = models.Employee.objects.get(user=self.request.user)
        serializer.save(employee=employee)

    def has_permission(self, request, view):
        if request.user.is_superuser:
            return True
        return super().has_permission(request, view)

perform_create метод будет вызван только в том случае, если пользователь не является суперпользователем и имеет права доступа. has_permission метод вернет True для суперпользователей.

Вы можете написать класс пользовательского разрешения следующим образом:

class CustomPermission(permissions.BasePermission):

    def has_permission(self, request, view):
        # Read permissions are allowed to any request,
        # so we'll always allow GET, HEAD or OPTIONS requests.
        if request.method in permissions.SAFE_METHODS:
            return True
        # write permission is allowed only for superusers
        return request.user.is_superuser

Тогда используйте это разрешение в своем представлении:

class MyViewSet(ModelViewSet):
    permission_classes = (IsAuthenticated, CustomPermission,)
    serializer_class = MySerializer

К сожалению, логика, которую вы хотите реализовать, используя Permission, невозможна, поскольку perform_create выполняет разрешение на уровне объекта, следовательно, логика должна быть в методе perform_create, как вы упомянули в вопросе.

Вы можете создать пользовательское разрешение смотрите следующий пример.

from rest_framework import permissions

class IsNotSuperuserPermission(permissions.BasePermission):
    message = 'You are super user.' # Your custom message.

    def has_permission(self, request, view):
        if request.user.is_authenticated:
            return not request.user.is_superuser
        self.message = 'you are not logged in' # your custom message
        return False



class MyViewSet(ModelViewSet):
    serializer_class = MySerializer
    queryset = MyClass.objects.all()

    def get_serializer_class(self):
        if self.request.user.is_superuser:
            return self.serializer_class 

        return serializers.MyUserSerializer 

    def get_permissions(self):
        if self.action == 'create':
            permission_classes = [IsNotSuperuserPermission]
        else:
            permission_classes = [IsAuthenticated]
        return [permission() for permission in permission_classes]

    def perform_create(self, serializer):
        employee = models.Employee.objects.get(user=self.request.user)
        serializer.save(employee=employee)

в get_permissions вы можете назначить одно или несколько разрешений на каждое действие.

Вернуться на верх