Як поширити помилку на методі create у серіалізаторі DRF?

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

class ConsultationViewset(BaseModelViewset, ListModelViewsetMixin, RetrieveModelViewsetMixin, CreateModelViewsetMixin, UpdateModelViewsetMixin):
    serializer_class = ConsultationSerializer
    ....
class ConsultationSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        consultation = ConsultationService.create_consultation(validated_data.pop('customer', None), validated_data)
        return consultation
def create_consultation(customer: CustomerFactory.Models.CUSTOMER, validated_data):
    if ticket is None:
            raise exceptions.PermissionDenied("No active ticket found for this customer, request is forbidden")

Моя мета полягає у тому, щоб надіслати підняте повідомлення у create_consultation у відповіді. Проте я продовжую отримувати AssertionError: create() did not return an object instance. замість цього. Я міг би надіслати користувацьке повідомлення, якщо повторно підняти помилку у наборі даних, як показано нижче, але це неправильно, оскільки помилка має вигляд AssertionError.

class ConsultationViewset(...):
    def perform_create(self, serializer):
        try:
            serializer.save()
        except AssertionError as e:
            raise exceptions.PermissionDenied('custom message')

Як правильно згенерувати помилку PermissionDenied

?

Когда вы используете Django REST Framework (DRF), метод serializers create() создаст и вернет новый объект. Ошибка возникает, как при вызове сериализатором функции create_consultation, но запроса нет, и возникает ошибка. Из-за этой ошибки метод create() ничего не возвращает. Вот почему вы получаете AssertionError: create() did not return an object instance

Вы можете попробовать отловить ошибку в сериализаторе

class ConsultationSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        try:
            consultation = ConsultationService.create_consultation(validated_data.pop('customer', None), validated_data)
            return consultation
        except exceptions.PermissionDenied as e:
            raise e
        except Exception as e:
            # Convert other exceptions to DRF exceptions if needed
            raise exceptions.ValidationError(str(e))

Вам не следует активировать PermissionDenied в методе create. это обрабатывается в представлении перед доступом к сериализатору. Итак, согласно документу разрешения, вам необходимо реализовать пользовательские разрешения и добавить их в классы разрешений в представлении.

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    message = 'No active ticket found for this customer, request is forbidden.'

    def has_permission(self, request, view) -> bool:
         return request.user.has_active_ticket()  # example
class ExampleView(APIView):
    def get_permissions(self) -> list[BasePermission]:
        permission_classes = self.permission_classes
        if self.request.method == "POST":
            permission_classes = (
                *permission_classes,
                CustomerAccessPermission,
            )
        return [permission() for permission in permission_classes]
Вернуться на верх