'How to handle create/update on multiple nested serializers?

I've been able to make creating/updating happen on nested serializers, but I can't seem to get it to work when there are multiple many to many nest serializers.

Models:

class Brand(models.Model):
    name = models.CharField(max_length=500)

class Incentive(models.Model):
    name = models.CharField(max_length=500)
    brands = models.ManyToManyField(Brand, related_name='incentives_brand')
    start_dt = models.DateTimeField(auto_now_add=False, blank=True, null=True)
    end_dt = models.DateTimeField(auto_now_add=False, blank=True, null=True)

class Version(models.Model):
    name = models.CharField(max_length=1000)
    incentives = models.ManyToManyField(Incentive, related_name='versions_incentive', blank=True)
    brands = models.ManyToManyField(Brand, related_name='versions_brand')

Serializers:

class BrandSerializer(serializers.ModelSerializer):    
    class Meta:
        model = Brand
        depth = 1
        fields = ['id', 'name']

class IncentiveSerializer(serializers.ModelSerializer):
    brands = BrandSerializer(many=True)
    
    class Meta:
        model = Incentive
        # depth = 1
        fields = ['id', 'name', 'brands', 'start_dt', 'end_dt']
    
class VersionSerializer(serializers.ModelSerializer): 
    incentives = IncentiveSerializer(many=True)
    brands = BrandSerializer(many=True)
       
    class Meta:
        model = Version
        fields = ['id', 'name', 'incentives', 'brands']
        
    def create(self, validated_data):
        brands = validated_data.pop('brands', [])
        incentives = validated_data.pop('incentives', [])
        instance = Version.objects.create(**validated_data)
        for brand_data in brands:
            brand = Brand.objects.get(**brand_data)
            instance.brands.add(brand)
        for incentive_data in incentives:
            incentive = Incentive.objects.get(**incentive_data)
            instance.incentives.add(incentive)
        return instance
    
    def update(self, instance, validated_data):
        brands = validated_data.pop('brands', [])
        incentives = validated_data.pop('incentives', [])
        instance = super().update(instance, validated_data)
        brand_objs = []
        incentive_objs = []
        for brand_data in brands:
            brand = Brand.objects.get(**brand_data)
            brand_objs.append(brand)
            instance.brands.set(brand_objs)
        for incentive_data in incentives:
            incentive = Incentive.objects.get(**incentive_data)
            incentive_objs.append(incentive)
            instance.incentives.set(incentive_objs)
        return instance 

I tried using the same format as with a single nested serializer. Now I'm getting a few different errors. Starting with Create I get:

TypeError: Field 'id' expected a number but got [OrderedDict([('name', 'Brand Test')])].

Then with PUT I get:

TypeError: Field 'id' expected a number but got [OrderedDict([('name', 'Brand Test')]), OrderedDict([('name', 'Brand 2 Test')]), OrderedDict([('name', 'Brand 3 Test')])]

I think the issue lies somewhere here. If any more code is needed please let me know(ex. views, urls). I'm guessing in the update I'm not properly emptying the list of brands. I just can't see it. Any help would be appreciated.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source