'Need to do POST method for the Nested serializers using django

models.py

class Organisation(models.Model):
    """
    Organisation model
    """
    org_id = models.AutoField(unique=True, primary_key=True)
    org_name = models.CharField(max_length=100)
    org_code = models.CharField(max_length=20)
    org_mail_id = models.EmailField(max_length=100)
    org_phone_number = models.CharField(max_length=20)
    org_address = models.JSONField(max_length=500, null=True)
    product = models.ManyToManyField(Product, related_name='products')
    org_logo = models.ImageField(upload_to=upload_org_logo, null=True, blank=True,)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

serializers.py

class Organisation_Serializers(serializers.ModelSerializer):
    product = Product_Serializers(read_only=True, many=True)

    class Meta:
        model = Organisation
        fields = ('org_id', 'org_name','org_address', 'org_phone_number', 'org_mail_id','org_logo','org_code','product',)
        #depth = 1

    def create(self, validated_data):
        org_datas = validated_data.pop('product')
        org = Organisation.objects.create(**validated_data)
        for org_data in org_datas:
            Product.objects.create(org=org, **org_data)
        return org

views.py

class Organisation_Viewset(DestroyWithPayloadMixin,viewsets.ModelViewSet):
    renderer_classes = (CustomRenderer, )  #ModelViewSet Provides the list, create, retrieve, update, destroy actions.
    queryset=models.Organisation.objects.all()
    parser_classes = [parsers.MultiPartParser, parsers.FormParser]
    http_method_names = ['get', 'post', 'patch', 'delete']
    serializer_class=serializers.Organisation_Serializers

I able to get the product data as a array of dict while performing GET method but while I tried to POST it, I'm getting an error as Key Error product. I need to get the data as I'm getting now and it would be fine if I POST based on the array of product_id or the array of data which I receive in the GET method. I was stuck on this part for 3 days and still I couldn't able to resolve it. Please help me resolve this issue your helps are much appreciated.



Solution 1:[1]

class Organisation_Serializers(serializers.ModelSerializer):
    product = Product_Serializers(many=True) # Remove read_only=True from here.

    class Meta:
        model = Organisation
        fields = '__all__'
        extra_kwargs = {
            "created_at": {"read_only": True},
            "updated_at": {"read_only": True},
        }

    def create(self, validated_data):
        # get the 'product' values from the payload.
        products = validated_data.pop('product')
        # Add (all) the value from payload to the Organisation model.
        organisation_instance = Organisation.objects.create(**validated_data)

        # Loop the values that were passed inside of products field from payload.
        for product in products:
            # Add normally the fields of "this payload" to the Product model.
            product_instance = Product.objects.create(**product)
            
            # Get the product_instance and passes all its payload.id.
            # adding them to organisation_instance as it should be.
            # like this the nested fields will be passed to the --
            # Organisation endpoint.
            # Organisation --> product field --> [product instances..]
            organisation_instance.product.add(product_instance.id)

           # save the modifications -
           # with the nested values.
           organisation_instance.save()

        return organisation_instance

Sources

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

Source: Stack Overflow

Solution Source
Solution 1 Elias Prado