Django Rest Framework receive primary key value in POST and return model object as nested serializer

I have been happy with my previous solution, but decided to look again and I think I have another solution that does exactly what you want.

Basically, you need to create your own custom field, and just overwrite the to_representation method:

class CarpoolField(serializers.PrimaryKeyRelatedField):
    def to_representation(self, value):
        pk = super(CarpoolField, self).to_representation(value)
        try:
           item = ParentArrival.objects.get(pk=pk)
           serializer = CarpoolSerializer(item)
           return serializer.data
        except ParentArrival.DoesNotExist:
           return None

    def get_choices(self, cutoff=None):
        queryset = self.get_queryset()
        if queryset is None:
            return {}

        return OrderedDict([(item.id, str(item)) for item in queryset])

class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
    carpool = CarpoolField(queryset=Carpool.objects.all())

    class Meta:
        model = ParentArrival

This will allow you to post with

{
     "carpool": 10
}

and get:

{
    "carpool": {
        "url": "http://localhost:8000/api/school-building-carpools/10/"
        "name": "Name of the carpool",
        ...
    }
}

It's simple. As you know, Django appends "_id" to the field name in the ModelClass, and you can achieve it in the SerializerClass, and the original filed can also be achieved. All you have to do is like this

class ParentArrivalSerializer(serializers.HyperlinkedModelSerializer):
    # ...
    carpool_id = serializers.IntegerField(write_only=True)
    carpool = SchoolBuildingCarpoolSerializer(read_only=True)
    # ...
    class Meta:
        fields = ('carpool_id', 'carpool', ...)

And use carpool_id in POST request.


How about overriding the to_representation method?

class YourSerializer(serializers.ModelSerializer):

    class Meta:
        model = ModelClass
        fields = ["id", "foreignkey"]

    def to_representation(self, instance):
        data = super(YourSerializer, self).to_representation(instance)
        data['foreignkey'] = YourNestedSerializer(instance.foreignkey).data
        return data