diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 8a810edb9..9b6b7dc3a 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -238,7 +238,7 @@ Nested relationships can be expressed by using serializers as fields. If the field is used to represent a to-many relationship, you should add the `many=True` flag to the serializer field. -## Example +## Read-only example For example, the following serializer: @@ -256,6 +256,15 @@ For example, the following serializer: Would serialize to a nested representation like this: + >>> album = Album.objects.create(album_name="The Grey Album", artist='Danger Mouse') + >>> Track.objects.create(album=album, order=1, title='Public Service Announcement', duration=0) + + >>> Track.objects.create(album=album, order=2, title='What More Can I Say', duration=0) + + >>> Track.objects.create(album=album, order=3, title='Encore', duration=0) + + >>> serializer = AlbumSerializer(instance=album) + >>> serializer.data { 'album_name': 'The Grey Album', 'artist': 'Danger Mouse', @@ -263,10 +272,52 @@ Would serialize to a nested representation like this: {'order': 1, 'title': 'Public Service Announcement'}, {'order': 2, 'title': 'What More Can I Say'}, {'order': 3, 'title': 'Encore'}, - ... ], } +## Writable nested serializers + +To use writable nested serialization you'll want to declare a nested field on +the serializer class, and write the `create(validated_data)` and/or +`update(instance, validated_data)` methods explicitly. +Note that nested serializers also works for regular serializers. + + class TrackSerializer(serializers.ModelSerializer): + class Meta: + model = Track + fields = ('order', 'title') + + class AlbumSerializer(serializers.ModelSerializer): + tracks = TrackSerializer(many=True) + + class Meta: + model = Album + fields = ('album_name', 'artist', 'tracks') + + def create(self, validated_data): + tracks_data = validated_data.pop('tracks') + album = Album.objects.create(**validated_data) + for track_data in tracks_data: + Track.objects.create(album=album, duration=0, **track_data) + return album + + >>> data = { + 'album_name': 'The Grey Album', + 'artist': 'Danger Mouse', + 'tracks': [ + {'order': 1, 'title': 'Public Service Announcement'}, + {'order': 2, 'title': 'What More Can I Say'}, + {'order': 3, 'title': 'Encore'}, + ], + } + >>> serializer = AlbumSerializer(data=data) + >>> serializer.is_valid() + True + >>> serializer.save() + + >>> + + # Custom relational fields To implement a custom relational field, you should override `RelatedField`, and implement the `.to_representation(self, value)` method. This method takes the target of the field as the `value` argument, and should return the representation that should be used to serialize the target. The `value` argument will typically be a model instance.