Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-serializerdjango-rest-viewsets

Django Rest Framework: Send full foreign key objects in GET response but accept only foreign ids in POST payload, without two serializers?


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"
}

Solution

  • 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']