Сериализатор Django DRF с many=true пропускает соответствующую функцию validate()
Я столкнулся со следующей проблемой:
Имеется 2 сериализатора CreateSerializer(дочерний) и BulkCreateSerializer(родительский). Они связаны через list_serializer_class. Я переопределил методы create() и validate() для обоих сериализаторов и ожидаю, что они будут срабатывать соответственно на то, приходит ли один экземпляр через POST или список экземпляров.
Однако, когда я отправляю post запрос со списком экземпляров, сериализатор действительно переключается на many=true, но использует validate(), принадлежащий дочернему CreateSerializer, вместо выделенного BulkCreateSerializer, что, конечно же, приводит к ошибкам.
Так что мой вопрос заключается в том, что может быть логикой под капотом, которая не позволяет моим сериализаторам распределять элементы для валидации соответственно? И как заставить его работать таким образом?
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")
не сработал, потому что возникли проблемы с проверкой дочерних сериализаторов, в результате чего сериализатор списка больше не запускается.