Создание объектов внешнего ключа внутри сериализатора

У меня есть две модели:

class Author(models.Model):
    name = models.CharField(max_length=255)

class Books(models.Model)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books_author')
    name = models.CharField(max_length=255)

Теперь мне нужно создать автора и связанные с ним книги в одном запросе внутри create serializer. Входящие данные будут выглядеть примерно так:

{
 "author": "John Doe"
 "books":[
     {
        "name": "Life of Pie"
     },
     {
        "name": "Lord of the rings"      
     }
  ]
 }

Как я могу сделать это без использования цикла for внутри сериализатора create?

Вложенные сериализаторы доступны только для чтения, вам нужно переопределить метод create, а самый простой метод - использовать цикл for.

# serializers.py

class BooksSerializer(serializers.ModelSerializer):

    class Meta:
        model = Books
        fields = ('name',)


class AuthorSerializer(serializers.ModelSerializer):
    books = BooksSerializer(source='books_author', many=True)

    def create(self, validated_data):
        books_data = validated_data.pop('books_author')
        author = Author.objects.create(**validated_data)
        for book in books_data:
            Books.objects.create(author=author, **book)
        return author

    class Meta:
        model = Author
        fields = ('name', 'books')

Обратите внимание, что я использовал "имя", а не "автор", так как это кажется более логичным, поэтому вам нужно использовать следующее тело:

{
    "name": "John Doe",
    "books": [
        {
            "name": "Life of Pie"
        },
        {
            "name": "Lord of the rings"
        }
    ]
}

То же самое относится к методу update.
Более подробно в официальной документации.


В качестве примечания, я бы:

  • переименуйте Books в Book (models.py)
  • измените related_name='books_author' на related_name='books' (models.py)
  • переименуйте BooksSerializer в BookSerializer (serializers.py)
  • замените books = BooksSerializer(source='books_author', many=True) на books = BooksSerializer(many=True)(serializers.py)

Это сделает ваш код более читабельным.

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