'Need to add one model fields in the another model serializers but throwing error while POST the request

models.py

class Product(models.Model):
    product_id = models.AutoField(unique=True, primary_key=True)
    product_name = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "product_master"

    def __str__(self):
        return self.product_name

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='org_logo/')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "organisation_master"

    def __str__(self):
        return self.org_name

serializers.py

class Product_Serializers(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('product_id', 'product_name',)

class Organisation_Serializers(serializers.ModelSerializer):
    product = Product_Serializers(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

" While i tried to do POST method for the organisation model I have tried giving the input for product as "product: 5" and "product: {"product_id": 5,"product_name": "time"} in the postman form data but it is showing as

{
    "status": "error",
    "code": 400,
    "data": {
        "product": [
            "This field is required."
        ]
    },
    "message": "success"
}

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 = [MultiPartParser, FormParser]
    serializer_class=serializers.Organisation_Serializers


    def create(self, request, *args, **kwargs):
        data = request.data
        new_organisation= models.Organisation.objects.create(org_name=data["org_name"],org_code = ["org_code"], org_mail_id =data["org_mail_id"],org_phone_number= data["org_phone_number"], org_address=data["org_address"],org_logo = data["org_logo"])

        new_organisation.save()

        for product in data["product"]:
            product_id = models.Product.objects.get(product_id=product["product_id"])
            new_organisation.products.add(product_id)

        serializer = serializers.Organisation_serializers(new_organisation)

        return Response(serializer.data)

I need to post like this product: {"product_id": 5,"product_name": "time"}, what fields are available in the product model it should be posted on this product field.

Can you please suggest me a way as i tried many ways as per my knowledge but it dosen't worked.



Solution 1:[1]

you are using a tuple for fields, put a comma behind product in youre fields. If you use a list then dont use an end comma

fields = ('org_id', 'org_name', 'org_address', 'org_phone_number', 'org_mail_id','org_logo','org_code','product',)
        depth = 1

Solution 2:[2]

Update your serializers to:

class Product_Serializers(serializers.Serializer):
    product_id = serializers.IntegerField()
    product_name = serializers.CharField(max_length=100)


class Organisation_Serializers(serializers.ModelSerializer):
    product = Product_Serializers(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

Update your views as:

class Organisation_Viewset(ModelViewSet):
    # ModelViewSet Provides the list, create, retrieve, update, destroy actions.
    renderer_classes = (CustomRenderer,)
    queryset = Organisation.objects.all()
    parser_classes = [MultiPartParser, FormParser, JSONParser]
    serializer_class = Organisation_Serializers

    def create(self, request, *args, **kwargs):
        serializer = Organisation_Serializers(data=request.data)
        serializer.is_valid(raise_exception=True)
        product_data = serializer.validated_data.pop('product')
        does_not_exist = []
        product_instances = []
        for product in product_data:
            try:
                product_instance = Product.objects.get(
                    product_id=product['product_id'],
                    product_name=product['product_name']
                )
                product_instances.append(product_instance)
            except Product.DoesNotExist:
                does_not_exist.append(product)
        if len(does_not_exist) > 0:
            return Response({
                'error': 'Product does not exist',
                'does_not_exist': does_not_exist
            }, status=400)
        organization = Organisation.objects.create(**serializer.validated_data)
        for product in product_instances:
            organization.product.add(product)
            organization.save()
        return Response(Organisation_Serializers(organization).data, status=201)

Now we can send the list of product objects for the create API:

curl --location --request POST 'http://localhost:8000/api/organization/' \
--header 'Content-Type: application/json' \
--data-raw '{
    "org_id": "12345",
    "org_name": "test organization",
    "org_address": "test",
    "org_phone_number": "12345",
    "org_mail_id": "[email protected]",
    "org_code": "12345",
    "product": [
        {
            "product_id": 1,
            "product_name": "test p1"
        },
        {
            "product_id": 2,
            "product_name": "test p2"
        }
    ]
}'

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
Solution 2