beda-software / drf-writable-nested

Writable nested model serializer for Django REST Framework
Other
1.07k stars 116 forks source link

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

Open akhilmathew001 opened 2 years ago

akhilmathew001 commented 2 years ago
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": "test@email.com"
        }]
    },
    {
        ----- Some fields ----
        "process": 38,
        "above_limit": 22,
        ----- Some fields ----
        "trigger": [{
            "name": "test",
            "threshold": 8
        }],

        "notification": [{
            "email": "test@email.com"
        }]
    }
]

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

wael-kad commented 2 years ago

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).

johnthagen commented 4 months ago

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.