Skip to content

Repository files navigation

DRF Writable Nested

Build Statuscodecovpypi

This is a writable nested model serializer for Django REST Framework which allows you to create/update your models with related nested data.

The following relations are supported:

  • OneToOne (direct/reverse)
  • ForeignKey (direct/reverse)
  • ManyToMany (direct/reverse excluding m2m relations with through model)
  • GenericRelation (this is always only reverse)

Requirements

  • Python (2.7, 3.5, 3.6)
  • Django (1.8, 1.9, 1.10, 1.11)
  • djangorestframework (3.5+)

Installation

pip install drf-writable-nested

Usage

For example, for the following model structure:

fromdjango.dbimportmodelsclassSite(models.Model):
url=models.CharField(max_length=100)
classUser(models.Model):
username=models.CharField(max_length=100)
classAccessKey(models.Model):
key=models.CharField(max_length=100)
classProfile(models.Model):
sites=models.ManyToManyField(Site)
user=models.OneToOneField(User)
access_key=models.ForeignKey(AccessKey, null=True)
classAvatar(models.Model):
image=models.CharField(max_length=100)
profile=models.ForeignKey(Profile, related_name='avatars')

We should create the following list of serializers:

fromrest_frameworkimportserializersfromdrf_writable_nestedimportWritableNestedModelSerializerclassAvatarSerializer(serializers.ModelSerializer):
image=serializers.CharField()
classMeta:
model=Avatarfields= ('pk', 'image',)
classSiteSerializer(serializers.ModelSerializer):
url=serializers.CharField()
classMeta:
model=Sitefields= ('pk', 'url',)
classAccessKeySerializer(serializers.ModelSerializer):
classMeta:
model=AccessKeyfields= ('pk', 'key',)
classProfileSerializer(WritableNestedModelSerializer):
# Direct ManyToMany relationsites=SiteSerializer(many=True)
# Reverse FK relationavatars=AvatarSerializer(many=True)
# Direct FK relationaccess_key=AccessKeySerializer(allow_null=True)
classMeta:
model=Profilefields= ('pk', 'sites', 'avatars', 'access_key',)
classUserSerializer(WritableNestedModelSerializer):
# Reverse OneToOne relationprofile=ProfileSerializer()
classMeta:
model=Userfields= ('pk', 'profile', 'username',)

Also, you can use NestedCreateMixin or NestedUpdateMixin from this package if you want to support only create or update logic.

For example, we can pass the following data with related nested fields to our main serializer:

data= {
'username': 'test',
'profile': {
'access_key': {
'key': 'key',
},
'sites': [
{
'url': 'http://google.com',
},
{
'url': 'http://yahoo.com',
},
],
'avatars': [
{
'image': 'image-1.png',
},
{
'image': 'image-2.png',
},
],
},
}
user_serializer=UserSerializer(data=data)
user_serializer.is_valid(raise_exception=True)
user=user_serializer.save()

This serializer will automatically create all nested relations and we receive a complete instance with filled data.

user_serializer=UserSerializer(instance=user)
print(user_serializer.data)
{
'pk': 1,
'username': 'test',
'profile': {
'pk': 1,
'access_key': {
'pk': 1,
'key': 'key'
},
'sites': [
{
'pk': 1,
'url': 'http://google.com',
},
{
'pk': 2,
'url': 'http://yahoo.com',
},
],
'avatars': [
{
'pk': 1,
'image': 'image-1.png',
},
{
'pk': 2,
'image': 'image-2.png',
},
],
},
}

It is also possible to pass through values to nested serializers from the call to the base serializer's save method. These kwargs must be of type dict. E g:

# user_serializer created with 'data' as aboveuser=user_serializer.save(
profile={
'access_key': {'key': 'key2'},
},
)
print(user.profile.access_key.key)
'key2'

Note: The same value will be used for all nested instances like default value but with higher priority.

Authors

2014-2017, beda.software

About

Writable nested model serializer for Django REST Framework

Resources

Stars

0 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages