from rest_framework import serializers
from .models import Author, Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'isbn', 'published_date']
class AuthorSerializer(serializers.ModelSerializer):
books = BookSerializer(many=True, read_only=True)
class Meta:
model = Author
fields = ['id', 'name', 'email', 'books']
class AuthorWithBooksWriteSerializer(serializers.ModelSerializer):
books = BookSerializer(many=True)
class Meta:
model = Author
fields = ['id', 'name', 'email', 'books']
def create(self, validated_data):
books_data = validated_data.pop('books')
author = Author.objects.create(**validated_data)
for book_data in books_data:
Book.objects.create(author=author, **book_data)
return author
def update(self, instance, validated_data):
books_data = validated_data.pop('books', None)
instance.name = validated_data.get('name', instance.name)
instance.email = validated_data.get('email', instance.email)
instance.save()
if books_data is not None:
# Simple approach: clear and recreate
instance.books.all().delete()
for book_data in books_data:
Book.objects.create(author=instance, **book_data)
return instance
Nested serializers display related data clearly but are read-only by default. To make them writable, I override create() and update() methods. For simple nesting, PrimaryKeyRelatedField or SlugRelatedField works well. For deeper nesting, I validate nested data and create/update related objects explicitly. Using source parameter, I can customize field names. I'm careful about N+1 queries when serializing nested data—prefetching in the viewset's queryset helps. This pattern balances API usability with database performance.