The `.create()` method does not support writable nested fields by default.

后端 未结 3 440
陌清茗
陌清茗 2020-12-06 01:49

I have a big problem regarding the serialization of a Many to Many relationship with intermediate model in DRF: If the request method is get everything works perfectly. But

相关标签:
3条回答
  • 2020-12-06 02:04

    I think that the cause for error: JSON parse error - No JSON object could be decoded is because you forgot to put .data at the 2nd line from @Ivan Semochkin solution: representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data.

    Thus I find out that I will stumble upon Keyword Error: 'event' from line: representation = super(EquipmentSerializer, self).to_representation(instance) since the EquipmentSeralizer object contain the intermediary assignment_set instead of event.

    Here are the end result adapting from @Ivan Semochkin solution I do. Correct me if I'm wrong/inappropriate in practice.

    class EquipmentSerializer(serializers.ModelSerializer): 
    
        class Meta: 
            model = Equipment 
            fields = '__all__'
    
        def create(self, validated_data):
            order = Order.objects.get(pk=validated_data.pop('assignment_set').get('id'))
            instance = Equipment.objects.create(**validated_data)
            Assignment.objects.create(Order=order, Equipment=Equipment)
            return instance
    
        def to_representation(self, instance):
            representation = super(EquipmentSerializer, self).to_representation(instance)
            representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data
            return representation 
    

    Please correct me if I'm wrong. I'm new to Django.

    0 讨论(0)
  • 2020-12-06 02:14

    Maybe for most people who is having the same issue, this question is a quite long.

    The short answer is that DRF does not support natively create method for nested serializers. so what to do?

    Simply overriding the default behaviour. Check out a full example in the Official DRF docs

    0 讨论(0)
  • 2020-12-06 02:15

    DRF does not support create method for nested serializers. If you want to show related fields in an extended layout and not only with pks then you can override the to_representation method instead of rewriting default mtm field. You should also override a create method, because of the third model in mtm link:

    class EquipmentSerializer(serializers.ModelSerializer): 
    
        class Meta: 
            model = Equipment 
            fields = '__all__'
    
        def create(self, validated_data):
            order = Order.objects.get(pk=validated_data.pop('event'))
            instance = Equipment.objects.create(**validated_data)
            Assignment.objects.create(Order=order, Equipment=instance)
            return instance
    
        def to_representation(self, instance):
            representation = super(EquipmentSerializer, self).to_representation(instance)
            representation['assigment'] = AssignmentSerializer(instance.assigment_set.all(), many=True).data
            return representation 
    

    Now it'll save mtm fields properly passing list of pks, like [1, 2, 3] and for representation of that mtm related model, EquipmentSerializer will use AssignmentSerializer.

    0 讨论(0)
提交回复
热议问题