(Comments)
In this article we will see about the Django rest framework nested serializers and how to create a DRF writable nested serializers. This tutorial is divided into two parts. In the first part we discuss about creating models, serializers and views. In the second part we discuss how to use nested serializers and how to create and update nested serializers.
PART 1:
Copy the below code to the models.py file of you Django app.
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models # Create your models here. class Musician(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) instrument = models.CharField(max_length=100) def __unicode__(self): return self.first_name class Album(models.Model): artist = models.ForeignKey(Musician, on_delete=models.CASCADE, related_name='album_musician', null=True, blank=True) name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField()
Here we have two models 'Musician' and 'Album' and the model 'Album' has ForeignKey to model 'Musician'.
The serializers for the above two models can be written as in the code snippet below. Create a file called serializers.py and copy the below code into it.
Before that to use the djangorestframework, make sure that you have it installed. You can install it by simply running the following command.
pip install djangorestframework
After that add 'rest_framework' to your installed apps in the settings.py file.
from .models import * from rest_framework import serializers, fields class AlbumSerializer(serializers.ModelSerializer): class Meta: model = Album fields = ('id', 'artist', 'name', 'release_date', 'num_stars') class MusicianSerializer(serializers.ModelSerializer): class Meta: model = Musician fields = ('id', 'first_name', 'last_name', 'instrument')
Now in the views.py file, copy the below code and save it.
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render from .models import * from .serializers import * from rest_framework import generics # Create your views here. class MusicianListView(generics.ListCreateAPIView): queryset = Musician.objects.all() serializer_class = MusicianSerializer class MusicianView(generics.RetrieveUpdateDestroyAPIView): serializer_class = MusicianSerializer queryset = Musician.objects.all() class AlbumListView(generics.ListCreateAPIView): queryset = Album.objects.all() serializer_class = AlbumSerializer class AlbumView(generics.RetrieveUpdateDestroyAPIView): serializer_class = AlbumSerializer queryset = Album.objects.all()
Once the views are ready, add urls to the urls.py file in your project folder. It will be in the same directory as the settings.py file.
url(r'^api/musicians/$', MusicianListView.as_view()), url(r'^api/musicians/(?P<pk>\d+)/$', MusicianView.as_view()), url(r'^api/albums/$', AlbumListView.as_view()), url(r'^api/albums/(?P<pk>\d+)/$', AlbumView.as_view()),
The output of the MusicianListView will be like this.
[ { "id": 1, "first_name": "ganesh", "last_name": "xeno", "instrument": "Guitar" } ]
I also added few albums. Here is the sample output.
[ { "id": 1, "artist": 1, "name": "NEO", "release_date": "2017-07-07", "num_stars": 4 }, { "id": 2, "artist": 1, "name": "NEO 2", "release_date": "2017-07-22", "num_stars": 4 } ]
Now if we want the 'Albums' details in the MusicianListView, we have modify the MusicianSerializer as shown below.
from .models import * from rest_framework import serializers, fields class AlbumSerializer(serializers.ModelSerializer): class Meta: model = Album fields = ('id', 'artist', 'name', 'release_date', 'num_stars') class MusicianSerializer(serializers.ModelSerializer): album_musician = AlbumSerializer(read_only=True, many=True) class Meta: model = Musician fields = ('id', 'first_name', 'last_name', 'instrument', 'album_musician')
Now the output of MusicianListView will be similar to the below code snippet.
[ { "id": 1, "first_name": "ganesh", "last_name": "xeno", "instrument": "Guitar", "album_musician": [ { "id": 1, "artist": 1, "name": "NEO", "release_date": "2017-07-07", "num_stars": 4 }, { "id": 2, "artist": 1, "name": "NEO 2", "release_date": "2017-07-22", "num_stars": 4 } ] } ]
As we can see now the Albums are show as list. But here the point is we can only read the data.
PART 2:
Now let's get into the actual topic of our post. That is writing data to this nested serializer. So let's go ahead and modify serializer code as shown below.
from .models import * from rest_framework import serializers, fields class AlbumSerializer(serializers.ModelSerializer): class Meta: model = Album fields = ('id', 'artist', 'name', 'release_date', 'num_stars') class MusicianSerializer(serializers.ModelSerializer): album_musician = AlbumSerializer(many=True) class Meta: model = Musician fields = ('id', 'first_name', 'last_name', 'instrument', 'album_musician') def create(self, validated_data): albums_data = validated_data.pop('album_musician') musician = Musician.objects.create(**validated_data) for album_data in albums_data: Album.objects.create(artist=musician, **album_data) return musician def update(self, instance, validated_data): albums_data = validated_data.pop('album_musician') albums = (instance.album_musician).all() albums = list(albums) instance.first_name = validated_data.get('first_name', instance.first_name) instance.last_name = validated_data.get('last_name', instance.last_name) instance.instrument = validated_data.get('instrument', instance.instrument) instance.save() for album_data in albums_data: album = albums.pop(0) album.name = album_data.get('name', album.name) album.release_date = album_data.get('release_date', album.release_date) album.num_stars = album_data.get('num_stars', album.num_stars) album.save() return instance
Sample data for creating and updating the MusicianSerializer is given below.
# Post data to the MusicianListView to create. { "first_name": "ganesh", "last_name": "xeno", "instrument": "Guitar", "album_musician": [ { "name": "NEO", "release_date": "2017-07-07", "num_stars": 5 }, { "name": "NEO 2", "release_date": "2017-07-22", "num_stars": 4 } ] } # PUT data to the MusicianListView to update data. { "id": 1, "first_name": "ganesh", "last_name": "xeno", "instrument": "Guitar", "album_musician": [ { "id": 1, "artist": 1, "name": "NEO", "release_date": "2017-07-07", "num_stars": 5 }, { "id": 2, "artist": 1, "name": "NEO 2", "release_date": "2017-07-22", "num_stars": 4 } ] }
That is it for this article. Let's catch up on some other interesting topic. You can leave your comments if you have any doubts or feedback.
We develop web applications to our customers using python/django/angular.
Contact us at hello@cowhite.com
Comments