0

Let's imagine we have next models:

class Radio(models.Model):
    name = models.CharField(...)

class Artist(models.Model):
    name = models.CharField(...)

class Song(models.Model):
    title = models.CharField(...)
    artist = models.ForeignKey(Artist, ...)

class Reproduction(models.Model):
    song = models.ForeignKey(Song...)
    radio = models.ForeignKey(Radio...)
    date = models.DateTimeField(...)

How should I create my serializer and view if I will receive in a POST: title: "Song title", artist:"Artist name", radio:"Radio name", date:"Reproduction date" and it's needed to create the artist and the song if they don't exist.

Thank you.

3 Answers 3

1

You can create a serializer like below

from rest_framework import serializers
class SARSerializer(serializers.ModelSerializer):
    song = serializers.CharField()
    artist = serializers.CharField()
    radio = serializers.CharField()

    def create(self, validated_data):
        radio, _ = Radio.objects.get_or_create(
            name=validated_data.get('radio'))
        artist, _ = Artist.objects.get_or_create(
            name=validated_data.get('artist'))
        song, _ = Song.objects.get_or_create(
            title=validated_data.get('title'), artist=artist)
        self.instance = Reproduction.objects.create(song=song, radio=radio, date=validated_data.get("date"))

    @property
    def data(self):
        return {
           "radio": self.instance.radio.name,
           "artist": self.instance.song.artist.name,
           "song": self.instance.song.title,
           "date": self.instance.name,
        }

    class Meta:
        model = Reproduction
        fields = ['song', 'artist', 'radio', 'date']

Sign up to request clarification or add additional context in comments.

Comments

0

If you want to add such logic in your models, you can override perform_create or create methods of your views and create artist/song before deserializing it.

2 Comments

So, In my ReproductionSerializer class I should add title as serializers.CharField and then overwrite create method to use it?
You need to override your view's perform_create method (in views.py). This method is run before your Reproduction is serialized. This means your Reproduction dict will have artist/song fields before its serialized. Hence you need to add serializers.CharField in your serializer as well.
0

please try this one ..You have to make serializer just for incoming data validation then save all data one by one in views ..

serializes.py

from rest_framework.serializers import(
     CharField,
     Serializer,
     )

lass SaveDataSerializer(Serializer):
    title = CharField()
    artist = CharField()
    radio = CharField()
    date = DateField()

views.py

from rest_framework.views import APIView
from .serializers.py import 
from rest_framework.response import Response


class SaveData(APIView):
    def post(self,request)
        data =request.data
        serializer  = SaveDataSerializer(data =data)
        if serializer.is_valid():
            radio_obj = Radio.objects.create(name=data['radio'])
            artist_obj = Artist.objects.create(name =data['artist'])
            song_obj = Song.objects.create(title=data['title'],artist=artist_obj)
            Reproduction.objects.create(song = song_obj ,radio =radio_obj ,date=data['date'])
            return Response('added successfully' ,200)

    return Response(serializer.errors,400)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.