drf-writable-nested icon indicating copy to clipboard operation
drf-writable-nested copied to clipboard

Creating multiple objects with drf-writable-nested WritableNestedModelSerializer not creating the nested relation objects

Open akhilmathew001 opened this issue 3 years ago • 2 comments

class AlarmListSerializer(serializers.ListSerializer):

    @classmethod
    def many_init(cls, *args, **kwargs):
        # Instantiate the child serializer.
        kwargs['child'] = cls()
        # Instantiate the parent list serializer.
        return AlarmListSerializer(*args, **kwargs)

    def create(self, validated_data):
        ret = []
        for item in validated_data:
            alarm_obj = self.child.create(item)
            ret.append(alarm_obj)
        return ret

class AlarmSerializer(WritableNestedModelSerializer):

    trigger = AlarmTriggerTimeSerializer(many=True, required=True)
    notification = AlarmNotificationUsersSerializer(many=True, required=True)
   
    class Meta:
        model = Alarm
        list_serializer_class = AlarmListSerializer
        fields = ['process',  'above_limit',
                  'below_limit', 'is_expired',
                  'is_active', 'trigger', 'notification']

    def create(self, validated_data):
        ['.. Some code ...']
        ret = super().create(validated_data)
        return ret

    def update(self, instance, validated_data):
        ['.. Some code ...']
        ret = super().update(instance, validated_data)
        return ret

I have a serializer like this. I used to pass multiple objects with nested relations to this serializer with many=True enabled from the view. Sample JSON is as follows;

[{
        ----- Some fields ----
		"process": 32,
		"above_limit": 21,
		----- Some fields ----
		"trigger": [{
			"name": "test",
			"threshold": 4
		}],
		"notification": [{
			"email": "[email protected]"
		}]
	},
	{
	  	----- Some fields ----
		"process": 38,
		"above_limit": 22,
		----- Some fields ----
		"trigger": [{
			"name": "test",
			"threshold": 8
		}],

		"notification": [{
			"email": "[email protected]"
		}]
	}
]

Here Alarm object is getting created, but its nested relations are not created. What can be wrong here

akhilmathew001 avatar Jul 06 '22 11:07 akhilmathew001

I guess this happens because, in the update_or_create_reverse_relations method, the related_data is got from self.get_initial() which will be an empty OrderedDict, since the initial_data in the case of creating multiple objects is a list (check the get_initial method for more context).

wael-kad avatar Sep 01 '22 14:09 wael-kad

I hit this issue as well when making a custom bulk-create endpoint that receives a list of serialized objects and calls

serializer = self.get_serializer(data=request.data, many=True)

I only discovered later that Models with nested Models within them never created those nested models.

To work around this, I had to manually iterate of the list in request.data and call self.get_serializer() each time within the loop.

johnthagen avatar Jun 13 '24 17:06 johnthagen