ListSerializer с дочерним полем PrimaryRelatedKeyField
При использовании метода is_valid ListSerializer выполняется кверисет PrimaryRelatedKeyField Serializer, указанного в качестве дочернего, для количества элементов в Списке. Кверисет оценивается столько раз, сколько элементов в списке. Есть ли способ избежать этого? Я хочу, чтобы количество SQL-исполнений было как можно меньше.
class BookSerializer(serializers.ModelSerializer):
title = serializers.CharField()
publisher = serializers.PrimaryKeyRelatedField(queryset=Publisher.objects.all(), source="publisher")
class BookListSerializer(serializers.ListSerializer):
child = BookSerializer()
def create(self, validated_data):
return Book.objects.bulk_create([Book(**book) for book in validated_data])
books = [
{'title': 'Django Basic', 'publisher': 1},
{'title': 'Django Advance', 'publisher': 2},
{'title': 'DRF Basic', 'publisher': 1},
{'title': 'DRF Advance', 'publisher': 2},
{'title': 'Django Professional', 'publisher': 2},
]
bookListSerializer = BookListSerializer(data=books)
# In validation, queryset ( Publisher.objects.all() ) is evaluated every times.
# In this example, it will be executed five times.
bookListSerializer.is_valid(raise_exception=True)
bookListSerializer.save()
Если мы определим его как IntegerField в Serializer, указанном в качестве дочернего, он не будет выполнять много наборов запросов, но нам придется проверять в другой части, правильно ли указан id или нет.
class BookSerializer(serializers.ModelSerializer):
title = serializers.CharField()
publisher = serializers.IntegerField()
class BookListSerializer(serializers.ListSerializer):
child = BookSerializer()
def create(self, validated_data):
return Book.objects.bulk_create([Book(**book) for book in validated_data])
books = [
{'title': 'Django Basic', 'publisher': 1},
{'title': 'Django Advance', 'publisher': 2},
{'title': 'DRF Basic', 'publisher': 1},
{'title': 'DRF Advance', 'publisher': 2},
{'title': 'Django Professional', 'publisher': 2},
]
# Need a validation
book_id_list = [book['publisher'] for book in books]
if len(book_id_list) != Book.filter(id__in=book_id_list).count():
raise serializers.ValidationError()
bookListSerializer = BookListSerializer(data=books)
bookListSerializer.is_valid(raise_exception=True)
bookListSerializer.save()