Сериализатор Django DRF с many=true пропускает соответствующую функцию validate()

Я столкнулся со следующей проблемой:

Имеется 2 сериализатора CreateSerializer(дочерний) и BulkCreateSerializer(родительский). Они связаны через list_serializer_class. Я переопределил методы create() и validate() для обоих сериализаторов и ожидаю, что они будут срабатывать соответственно на то, приходит ли один экземпляр через POST или список экземпляров.

Однако, когда я отправляю post запрос со списком экземпляров, сериализатор действительно переключается на many=true, но использует validate(), принадлежащий дочернему CreateSerializer, вместо выделенного BulkCreateSerializer, что, конечно же, приводит к ошибкам.

Example when I post list of items:

Так что мой вопрос заключается в том, что может быть логикой под капотом, которая не позволяет моим сериализаторам распределять элементы для валидации соответственно? И как заставить его работать таким образом?

serializers.py

views.py

class DraftsRecipeStepsCreateView(APIView):
    
    serializer_class = RecipeStepDraftCreateSerializer  

    def post(self, request, *args, **kwargs):

        print(f'DATA IS LIST: {isinstance(request.data, list)}')
        
        serializer = self.serializer_class(
            data=request.data, 
            many=isinstance(request.data, list), 
            context={
                'request': request,
                'recipe_id': kwargs.get('recipe_id')})
        serializer.is_valid(raise_exception=True)
        serializer.save()   
        return Response(serializer.data, status=status.HTTP_201_CREATED)

Код, объясняющий такое поведение, можно найти here. Он описывает, как сериализатор списков выполняет валидацию (метод run_validation).

Исходя из этого, сериализатор списка сначала проверяет каждый дочерний сериализатор, как показано в реализации to_internal_value:

    def to_internal_value(self, data):
        ...
        for item in data:
            try:
                validated = self.child.run_validation(item)
            except ValidationError as exc:
                errors.append(exc.detail)
            else:
                ret.append(validated)
                errors.append({})
        ...

перед выполнением собственного списка проверьте:

    def run_validation(self, data=empty):
        ...
        value = self.to_internal_value(data) # <-- children validation first
        try:
            self.run_validators(value) # <-- then the list validation
        ...

Я попробовал это с нижеприведенным сериализатором:

class MyModelListSerializer(serializers.ListSerializer):
    def validate(self, attrs):
        print('mymodel list validate')
        return attrs


class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'
        list_serializer_class = MyModelListSerializer

    def validate(self, attrs):
        print('mymodel validate')
        return attrs

используя некоторые выборочные данные, а затем проверяя:

somedata = [
    {
        "data": "1",
    },
    {
        "data": "2",
    }
]
s = MyModelSerializer(data=somedata, many=True); s.is_valid();

Вывод, который я получаю, соответствует тому, что предлагает источник:

mymodel validate
mymodel validate
mymodel list validate

В вашем случае я подозреваю, что print("bulk validate") не сработал, потому что возникли проблемы с проверкой дочерних сериализаторов, в результате чего сериализатор списка больше не запускается.

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