Skip to main content

Writable nested helpers for django-rest-framework's serializers

Project description

DRF Writable Nested
====================
[![Build Status](https://travis-ci.org/Brogency/drf-writable-nested.svg?branch=master)](https://travis-ci.org/Brogency/drf-writable-nested)
[![codecov](https://codecov.io/gh/Brogency/drf-writable-nested/branch/master/graph/badge.svg)](https://codecov.io/gh/Brogency/drf-writable-nested)

This is a writable nested model serializer for Django REST Framework.

Requirements
============

- Python (2.7, 3.2, 3.3, 3.4, 3.5)
- Django (1.8, 1.9, 1.10)
- djangorestframework (3.x)

Installation
============

```
pip install drf-writable-nested
```

Usage
=====
For example, for the following model structure:
```python
from django.db import models


class Site(models.Model):
url = models.CharField(max_length=100)


class User(models.Model):
username = models.CharField(max_length=100)


class AccessKey(models.Model):
key = models.CharField(max_length=100)


class Profile(models.Model):
sites = models.ManyToManyField(Site)
user = models.OneToOneField(User)
access_key = models.ForeignKey(AccessKey, null=True)


class Avatar(models.Model):
image = models.CharField(max_length=100)
profile = models.ForeignKey(Profile, related_name='avatars')
```

We should create the following list of serialzers:

```python
from rest_framework import serializers
from drf_writable_nested import WritableNestedModelSerializer


class AvatarSerializer(serializers.ModelSerializer):
image = serializers.CharField()

class Meta:
model = Avatar
fields = ('pk', 'image',)


class SiteSerializer(serializers.ModelSerializer):
url = serializers.CharField()

class Meta:
model = Site
fields = ('pk', 'url',)


class AccessKeySerializer(serializers.ModelSerializer):

class Meta:
model = AccessKey
fields = ('pk', 'key',)


class ProfileSerializer(WritableNestedModelSerializer):
# Direct ManyToMany relation
sites = SiteSerializer(many=True)

# Reverse FK relation
avatars = AvatarSerializer(many=True)

# Direct FK relation
access_key = AccessKeySerializer(allow_null=True)

class Meta:
model = Profile
fields = ('pk', 'sites', 'avatars', 'access_key',)


class UserSerializer(WritableNestedModelSerializer):
# Reverse OneToOne relation
profile = ProfileSerializer()

class Meta:
model = User
fields = ('pk', 'profile', 'username',)

# Optional callback - will be called after reverse relations will be saved
def after_reverse_relations_saved(self, instance):
after_reverse_relations_saved_callback()

# Optional callback - will be called after profile relation will be saved
def after_profile_saved(self):
after_profile_saved_callback()
```

Also, you can use `NestedCreateMixin` or `NestedUpdateMixin` if you want
to implement only create or update logic.

For example, if we have `/user/` endpoint for user creation with `UserSerializer`,
we should send the following data:

```json
{
"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"
}
]
}
}
```

This serializer automatically will create all relations and we can see the output
like the following example:
```json
{
"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"
}
]
}
}
```

Authors
=======
Bro.engineering

Project details


Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page