Serializing ManyToMany in Django Rest Framework (2

2019-06-15 22:32发布

I have what I assumed to be a pretty simple serializer setup, but when I attempt to PUT data to my API, I get the following error:

ValueError: instance should be a queryset or other iterable with many=True

Here's the view:

class QuizAPI(generics.RetrieveUpdateDestroyAPIView):
    model = Quiz
    serializer_class = QuizSerializer
    lookup_field = 'activity_id'

and the serializers:

class MediaResourceSerializer(serializers.ModelSerializer):
    owner = serializers.PrimaryKeyRelatedField(many=False, read_only=True)

    class Meta:
        model = MediaResource
        fields = ('owner', 'name', 'type', 'url')

class AnswerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Answer
        fields = ('text','is_correct','order')

class QuestionSerializer(serializers.ModelSerializer):
    answers = AnswerSerializer(many=True, required=False)
    resources = MediaResourceSerializer(many=True, required=False)

    class Meta:
        model = Question
        fields = ( 
            'question_id', 
            'type', 
            'order', 
            'question_text', 
            'explanation', 
            'resources', 
            'grading_weight', 
            'answers' 
        )

class QuizSerializer(serializers.ModelSerializer):
    questions = QuestionSerializer(many=True, required=False)
    created_by = serializers.PrimaryKeyRelatedField(many=False, read_only=True)

    class Meta:
        model = Quiz
        fields = (
            'activity_id', 
            'name',  
            'is_hidden', 
            'created_by', 
            'created_date', 
            'last_updated', 
            'sharable', 
            'questions'
        )

If I comment out the 'questions' field from QuizSerializer it runs just fine (of course without question data).

** Edit: Here's the PUT call payload:

activity_id: 4
created_by: 1
created_date: "2013-07-29T20:39:47.981Z"
is_hidden: false
last_updated: null
name: "This is only a test"
questions: []
sharable: true

2条回答
何必那么认真
2楼-- · 2019-06-15 23:10

with nested relationship between models, in my opinion, best and easiest way is to use different serializators

My case

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return GetUserModelSerializer
        else:
            return UserModelSerializer

Your case:

class QuizAPI(generics.RetrieveUpdateDestroyAPIView):
    model = Quiz
    #serializer_class = QuizSerializer
    lookup_field = 'activity_id'

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return QuizNestedSerializer
        else: # Means POST, PUT etc.
            return QuizSimpleSerializer

class QuizSimpleSerializer(serializers.ModelSerializer):
    # remove these lines
    # questions = QuestionSerializer(many=True, required=False)
    # created_by = serializers.PrimaryKeyRelatedField(many=False, read_only=True)

    class Meta:
        model = Quiz
        fields = (
            'activity_id', 
            'name',  
            'is_hidden', 
            'created_by', 
            'created_date', 
            'last_updated', 
            'sharable', 
            'questions'
        )

class QuizNestedSerializer(serializers.ModelSerializer):
    questions = QuestionSerializer(many=True, required=False)
    created_by = serializers.PrimaryKeyRelatedField(many=False, read_only=True)

    class Meta:
        model = Quiz
        fields = (
            'activity_id', 
            'name',  
            'is_hidden', 
            'created_by', 
            'created_date', 
            'last_updated', 
            'sharable', 
            'questions'
        )
查看更多
冷血范
3楼-- · 2019-06-15 23:27

The problem looks to be that nested representations do not support read–write, and serializing flat structures for write operations is the way to go.

查看更多
登录 后发表回答