Проверка разрешений Django Rest Framework при создании

Почему django rest framework не проверяет разрешения объекта при создании объекта? Нет никакого смысла (для меня, во всяком случае), что пользователь должен иметь возможность создавать объект, который он не может видеть, обновлять или удалять. В настоящее время я подкласс

class CheckCreatePermissionsViewSet(ModelViewSet):
    def perform_create(self, serializer):
    '''
    Called by create before calling serializer.save()
    '''
    obj = serializer.save()
    try:
        self.check_object_permissions(obj)
    except:
        obj.delete()
        raise

Почему это не реализовано по умолчанию? Это вызвало у меня сильную головную боль, и я не могу придумать ни одной причины, по которой это будет реализовано следующим образом.

2 ответа

Я считаю более естественным и ясным, что вы вызываете проверку бизнес-логики перед созданием объекта, а не создания объекта и выяснения, может ли пользователь увидеть его, чтобы удалить его.

class CheckCreatePermissionsViewSet(ModelViewSet):
    def perform_create(self, serializer):
        try:
            business_rules_are_ok(serializer.data, user):
        except BusinessException:
            raise ValidationError(<content from BusinessException)
        serializer.save()

Если вы не хотите создавать объект, если у пользователя нет определенных разрешений, вы можете использовать allow_classes внутри Viewset, чтобы viewset даже не позволил пользователю создать объект.

Зачем вам нужно создать, а затем снова удалить на основании разрешения?. Лучше предварительно проверить разрешение, чтобы объект не создавался даже в случае сбоя разрешения.

Например, если вы хотите, чтобы только Администратор создал объект, вы можете добавить permission_classes=[permissions.IsAdminUser] в viewset, так что элемент управления даже не входит внутрь execute_create. Viewset отправит 403, если обычный пользователь попытался создать объект. Надеюсь, это то, что вы хотели.

В моем подходе я использовал Perform_create, чтобы выполнить работу, как вы предложили. Однако вместо создания и удаления я использовал транзакцию, чтобы позаботиться о ней, код:

class CheckCreatePermissionsViewSet(ModelViewSet):
    def check_object_permissions(self, request, obj):
        super(type(self), self).check_object_permissions(request, obj)
        #Additional logic....
        if not request.user.is_staff:
            raise PermissionDenied()


    def perform_create(self, serializer):
        with transaction.atomic():
            super(type(self), self).perform_create(serializer)
            obj = serializer.instance
            self.check_object_permissions(self.request, obj)
Другие вопросы по тегам