Home > Enterprise >  POST request for nested objects
POST request for nested objects

Time:09-23

I have models like this

class Survey(models.Model):
    name = models.CharField(max_length=120)
    ...


class Question(models.Model):
    survey = models.ForeignKey(Survey,
                               related_name='questions',
                               on_delete=models.CASCADE)
    ...


class Option(models.Model):
    question = models.ForeignKey(Question,
                                 related_name='options',
                                 on_delete=models.CASCADE)
    ...

Serializers looks like:

class OptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Option
        exclude = ('question','id')


class QuestionSerializer(serializers.ModelSerializer):
    options = OptionSerializer(many=True)
    class Meta:
        model = Question
        exclude = ('survey',)


class SurveyDetailSerializer(serializers.ModelSerializer):
    creator = serializers.StringRelatedField(read_only=True)
    questions = QuestionSerializer(many=True)

    class Meta:
        model = Survey
        exclude = ('is_active',)

GET request is clear, i get survey with all questions and options

views.py

class SurveyDetailView(generics.RetrieveAPIView):
    """Detail Survey view with all survey's questions"""
    queryset = Survey.objects.all()
    serializer_class = SurveyDetailSerializer

Result

{
    "id": 3,
    "creator": "nvbr",
    "questions": [
        {
            "id": 5,
            "options": [
                {
                    "text": "OPTION A"
                },
                {
                    "text": "OPTION B"
                }
            ],
            "answer_type": "single option",
            "text": "QUESTION 1?"
        }
    ],
    "name": "stackoverflow survey",
    "description": "Example",
    "created_at": "2021-09-23T13:07:19.679174Z"
}

but how can I make POST to save Survey, Questions and Options? Or should I always create separate endpoints for all models? SPA frontend if it important

CodePudding user response:

Ah, welcome to the limitations of DRF.

Presently, the way to work with nested data is by overriding the update method on your serializer:

serializers.py

class SurveyDetailSerializer(serializers.ModelSerializer):

    ...

    def update(self, instance, validated_data):

        # get the questions array:
        questions = validated_data.pop('questions')
        
        # create new questions, map to survey 
        ...

        # continue with regular update method:
        super().update(self, instance, validated_data)
  • Related