В Django есть десятки сообщений о n + 1 запросах во вложенных отношениях, но я не могу найти ответ на свой вопрос.Вот контекст:
Модели
class Book(models.Model):
title = models.CharField(max_length=255)
class Tag(models.Model):
book = models.ForeignKey('app.Book', on_delete=models.CASCADE, related_name='tags')
category = models.ForeignKey('app.TagCategory', on_delete=models.PROTECT)
page = models.PositiveIntegerField()
class TagCategory(models.Model):
title = models.CharField(max_length=255)
key = models.CharField(max_length=255)
В книге много тегов, каждый тег относится к категории тегов.
Сериализаторы
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
exclude = ['id', 'book']
class BookSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True, required=False)
class Meta:
model = Book
fields = ['title', 'tags']
def create(self, validated_data):
with transaction.atomic():
tags = validated_data.pop('tags')
book = Book.objects.create(**validated_data)
Tag.objects.bulk_create([Tag(book=book, **tag) for tag in tags])
return book
Проблема
Я пытаюсь отправить POST в BookViewSet со следующими данными примера:
{
"title": "The Jungle Book"
"tags": [
{ "page": 1, "category": 36 }, // plot intro
{ "page": 2, "category": 37 }, // character intro
{ "page": 4, "category": 37 }, // character intro
// ... up to 1000 tags
]
}
Это все работает, однако во время публикации сериализатор выполняет вызов для каждого тега, чтобы проверить, является ли category_id
действительным:
![enter image description here](https://i.stack.imgur.com/ZJOOm.png)
Поскольку в вызове может быть до 1000 вложенных тегов, я не могу себе этого позволить.
Как мне «выполнить предварительную выборку» для проверки?
Если это невозможно, как отключить проверку, которая проверяет наличие в базе данных идентификатора Foreign_key?
РЕДАКТИРОВАТЬ:Дополнительная информация
Вот вид:
class BookViewSet(views.APIView):
queryset = Book.objects.all().select_related('tags', 'tags__category')
permission_classes = [IsAdminUser]
def post(self, request, format=None):
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)