DRF Writable Nested
drf-writable-nested provides helpers for django-rest-framework (DRF) serializers, enabling creation and update of nested objects in a single API call. It simplifies handling related fields, especially for one-to-many and many-to-many relationships, making nested serializer operations more intuitive. The current version is 0.7.2, and it maintains an active release cadence, frequently updating for new Django, DRF, and Python versions.
Warnings
- breaking Version 0.7.2 dropped support for Python 3.8. Additionally, version 0.7.1 dropped support for Python <3.7, Django <4.2, and DRF <3.14.
- gotcha Nested object deletion with `on_delete=SET(fn)` is not fully supported; related objects might still be deleted as they were in previous releases, rather than having their foreign keys set by the function.
Install
-
pip install drf-writable-nested
Imports
- WritableNestedModelSerializer
from drf_writable_nested.serializers import WritableNestedModelSerializer
- UniqueFieldsMixin
from drf_writable_nested.mixins import UniqueFieldsMixin
Quickstart
from django.db import models
from rest_framework import serializers
from drf_writable_nested.serializers import WritableNestedModelSerializer
# Define models
class Planet(models.Model):
name = models.CharField(max_length=100, unique=True)
population = models.BigIntegerField(default=0)
def __str__(self):
return self.name
class Moon(models.Model):
name = models.CharField(max_length=100, unique=True)
planet = models.ForeignKey(Planet, on_delete=models.CASCADE, related_name='moons')
def __str__(self):
return self.name
# Define nested serializer for Moon
class MoonSerializer(serializers.ModelSerializer):
class Meta:
model = Moon
fields = ['id', 'name']
# Define main serializer for Planet using WritableNestedModelSerializer
class PlanetSerializer(WritableNestedModelSerializer):
moons = MoonSerializer(many=True, required=False)
class Meta:
model = Planet
fields = ['id', 'name', 'population', 'moons']
# Example usage (requires Django setup, e.g., via manage.py shell)
# p = Planet.objects.create(name='Earth', population=8000000000)
# m = Moon.objects.create(name='Luna', planet=p)
# print(PlanetSerializer(p).data)
# Create a new planet with moons
# data = {
# 'name': 'Mars',
# 'population': 0,
# 'moons': [
# {'name': 'Phobos'},
# {'name': 'Deimos'}
# ]
# }
# serializer = PlanetSerializer(data=data)
# serializer.is_valid(raise_exception=True)
# new_planet = serializer.save()
# print(new_planet.name, new_planet.moons.all())
# Update an existing planet and its moons
# existing_earth = Planet.objects.get(name='Earth')
# update_data = {
# 'population': 8100000000,
# 'moons': [
# {'id': Moon.objects.get(name='Luna').id, 'name': 'The Moon'},
# {'name': 'New Moon'}
# ]
# }
# serializer = PlanetSerializer(existing_earth, data=update_data, partial=True)
# serializer.is_valid(raise_exception=True)
# updated_planet = serializer.save()
# print(updated_planet.name, updated_planet.moons.all())