1

I'm trying to write a create method that will write my nested fields but am finding that the nested object isn't written.

This is the sample I was using:

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

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

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(**validated_data)
        Profile.objects.create(user=user, **profile_data)
        return user

But I'm failing to understand what the user=user refers to.

Here is my code:

class MessagesSerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.IntegerField(source='pk', read_only=True)
    suggested_songs = SongSerializer()

    class Meta:
        model = Messages
        fields = ('id','owner','url','suggested_songs',)
        #fields = ('id','url','suggested_songs',)

    def create(self, validated_data):
        song_data = validated_data.pop('suggested_songs')
        message = Messages.objects.create(**validated_data)
        Song.objects.create(**song_data)
        return message

class SongSerializer(serializers.HyperlinkedModelSerializer):
    #id = serializers.IntegerField(source='pk', read_only=True)

    class Meta:
        model = Song
        fields =     ('id','title','artist','album','albumId','num_votes','cleared')
    read_only_fields = ('song_id')


class Messages(models.Model):
    owner = models.OneToOneField(User, primary_key=True,     related_name='user_messages', editable=False) #TODO, change owner to 'To'
    #suggested_songs = models.ManyToManyField(Song, related_name='suggested_songs')
    suggested_songs = models.ForeignKey(Song, null=True, blank=True)



    # If a user is added, this runs. 
    @receiver(post_save, sender=User)
    def create_friend_for_user(sender, instance=None, created=False, **kwargs):
        if created:
            Messages.objects.get_or_create(owner=instance)

    # Same as above, but for deletion 
    @receiver(pre_delete, sender=User)
    def delete_friend_for_user(sender, instance=None, **kwargs):
        if instance:
           Messages.objects.get(owner=instance).delete()

class Song(models.Model):
    """
    A model which holds information about the songs.
    """
    #song_id = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=150, blank=True, default='')
    artist = models.CharField(max_length=150, blank=True, default='')
    album = models.CharField(max_length=150, blank=True, default='')
    albumId = models.CharField(max_length=150, blank=True, default='')
    num_votes = models.IntegerField(default=0, blank=True)
    cleared = models.BooleanField(default=False, blank=True)

    class Meta:
        ordering = ('title',)
        #managed=True
1
  • You mean that the Song and Messages objects are created but not linked together or the Song is not created at all? Commented May 3, 2015 at 11:35

1 Answer 1

3

I think that the issue might be in the MessageSerializer.create method:

def create(self, validated_data):
        # here you are popping the suggested songs
        song_data = validated_data.pop('suggested_songs')
        # so when you create the message here the foreign key is set to NULL
        message = Messages.objects.create(**validated_data)
        # and here you create the Song instance correctly but it is not
        # associated with the message
        Song.objects.create(**song_data)
    return message

You need to pass the foreign key to the Messages.create method like in the example you have.

def create(self, validated_data):
        song_data = validated_data.pop('suggested_songs')
        song = Song.objects.create(**song_data)
        # song need to be created first because the foreign key is in
        # the Messages model
        message = Messages.objects.create(suggested_songs=song, **validated_data)
        return message

I hope this helps!

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

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.