Django Rest Framework writtable nested serializer is missing m2m field content

Viewed 240

I'm trying while creating object A, create object B, which are in many-to-many relation. I've read about it for some time already and I've created custom create() method in serializer to create associated B objects while creating A object, but there's no trace of B content in validated_data. My models:

    class A(models.Model):
        name = models.CharField('Name', max_length=250)
        description = models.TextField('Content')
        timestamp = models.DateTimeField('Timestamp', auto_now_add=True)
        b_field = models.ManyToManyField(B, blank=True, null=True, verbose_name='b', related_name='a')

    class B(models.Model):
        name = models.CharField('Name', max_length=250)
        description = models.TextField('Description')
        timestamp = models.DateTimeField('Timestamp', auto_now_add=True)

And A serializer:

    class ASerializer(serializers.ModelSerializer):
        b = BSerializer(many=True, required=False)

        class Meta:
            model = A
            fields = '__all__'
            read_only_fields = ['pk', 'timestamp']

        def create(self, validated_data):
            bs = validated_data.pop('b')
            a = A.objects.create(**validated_data)
            for b in bs:
                B.objects.create(**b)
            return a

I've been printing content of validated_data at the begginging of create() method and it looked like this:

{'name': 'test', 'description': 'none'}

So, no trace of B content. I've been testing with postman, sending something like this:

{
    "name": "test",
    "description": "none",
    "b": [
        {
            "id": 1,
            "name": "b test",
            "description": "none b",
        }
    ]
}
1 Answers

Okay, so I managed to solve it by myself (almost). drf-writtable-nested to the rescue. First of, I changed my A serializer so it now inherits after WritableNestedModelSerializer from package mentioned above. Thanks to this, content of b is now visible in validated_data passed to create() method. Speaking of which, from what I have read (and what can be seen in the question itself), there's a need to create m2m objects in overwritten create() method. Mine looks like this now:

def create(self, validated_data):
    bs_data = validated_data.pop('b')
    a = self.Meta.model.objects.create(**validated_data)

    for b_data in bs_data:
        b = B.objects.create(**b_data)
        a.b.add(b)
    return a

There's still place to validate B instance in this serializer, but let's say, this solves my issue.

Related