Как применить разрешения на 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
вы можете назначить одно или несколько разрешений на каждое действие.