Posting a foreign key relationship in Django Rest Framework

Resurrecting this old thread since it seems to be a common issue people are running into. I just got this working on Django 3.1.6.

Since the Topic and Content models are already linked, the serializer is simply

class ContentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Content
        fields = ('title', 'body', 'topic')

No need for topic = TopicSerializer(read_only=False), which will require you to create a new topic with the POST. Now, the body of the POST can be

{
    "title": "My blog post",
    "body" : ".....",
    "topic": 3
}

If you want your GET output to look like

{
    "title": "My blog post",
    "body" : ".....",
    "topic": {
        "id": 3
        "name": "announcements"
    }
}

override to_representation

class ContentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Content
        fields = ('title', 'body', 'topic')

    def to_representation(self, instance):
        response = super().to_representation(instance)
        response['topic'] = TopicSerializer(instance.topic).data
        return response

Credit for proper usage of to_representation goes to this answer by @PdotNJ


This is from your serializer.

     topic = TopicSerializer(read_only=True)

It means your topic is read only so when you are trying to save your serializer, topic is not getting saved. Remove that and problem would be fixed.

EDIT:

Now as per the second error, it is because it is expecting a dict and you are passing the model instance, so you have two options. Either create the dict by hand.

topic_dict = { "name": topic.name }

and pass that as 'topic' in request.data and then save or give the topic_id, as there is a foreign key relationship, it should work.

So it would be something like:

request.data["topic_id"] = topic.id

Now what you choose to do is totally upto you.