5

Say I've two models:

class Singer((models.Model):
   name = models.CharField(max_length=200)

class Song(models.Model):
   title = models.CharField(max_length=200)
   singer = models.ForeignKey(Singer)

And two serializers like:

class SingerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Singer
        fields = '__all__'

class SongSerializer(serializers.ModelSerializer):
    singer = SingerSerializer()

    class Meta:
        model = Singer
        fields = '__all__'

I've defined the serializers as above because I need the full foreign key object in the GET response for songs:

{
    "singer": {
        "id": 1,
        "name": "foo"
    },
    "id": 1,
    "title": "foo la la"
}

Is there a way to allow POST/PATCH payloads to only send in the id of the foreign object and not the entire object, without writing a different serializer? I'd like the PATCH payload to be so:

{
    "singer": 1,
    "id": 1,
    "title": "foo la la"
}
Judy T Raj
  • 1,755
  • 3
  • 27
  • 41

1 Answers1

4

You can achieve that by defining read_only and write_only fields. Also by using SlugRelatedFieldallows DRF to automatically populate it from a field on the related model.

Haven't tested this code, but the idea still stands.

class SongSerializer(serializers.ModelSerializer):
    singer = SingerSerializer(read_only=True)
    singer_id = serializers.SlugRelatedField(queryset=Singer.objects.all(), slug_field='singer', write_only=True)

    class Meta:
        model = Singer
        fields = ['singer', 'signer_id']
Yuval
  • 1,202
  • 10
  • 15
  • I think this works. Let me test it out and then approve. Thanks – Judy T Raj Feb 08 '21 at 06:11
  • If that solved your problem it will be greatly appreciated if you could mark my answer as correct, to help other people who seek an answer. If it does not yet solve your question, I will gladly try to help. – Yuval Feb 10 '21 at 18:10
  • I think it should be `model = Song` instead of `model = Singer`. – Val Berthe Jul 14 '22 at 14:24