I\'m trying to use my api to create and update products in a bundle. I did so:
model.py
class Business(models.Model):
name = models.CharField(max
In my experience, if you want to update a model and a related model in one request, with DRF, the easiest way to do this is to override the "create" method of a serializer. There's a good video on this here which I used as my reference: https://www.youtube.com/watch?v=EyMFf9O6E60
If you are making post via BundleSerializer you need to pass products with list of ProductSerializer data not just id since products in BundleSerializer is accepting productsSerializer data. You are getting type error 'name' is an invalid keyword argument for this function" because your validated_data contain name and BundleProduct object Does not have name field.And you are creating BundleProduct objects with validated_data.
Create bundle object and pass id of bundle object to BundleProduct object.
If you do not want to create product and just pass existing product id you need to make ListField
You need to Override get_fields and check the requests
Below is solution for POST Request
For PATCH AND PUT Request you need to override update method of ModelSerializer and handle the products accordingly.
class BundleSerializer(serializers.ModelSerializer):
def create(self, validated_data):
products = validated_data.pop('products')
bundle = Bundle.objects.create(**validated_data)
for product_id in products:
product = get_object_or_404(Product, pk=product_id)
BundleProduct.objects.create(product=product, bundle=bundle)
return bundle
class Meta:
model = Bundle
fields = "__all__"
def to_representation(self, instance):
repr = super().to_representation(instance)
repr['products'] = ProductSerializer(instance.products.all(), many=True).data
return repr
def get_fields(self):
fields = super().get_fields()
if self.context['request'].method in ['POST', "PATCH","PUT"]:
fields['products'] = serializers.ListField(
write_only=True,
child=serializers.IntegerField()
)
return fields
sample POST data to BundleSerializer
{
"products":[1,2],
"name":"Offer One",
"description":"description",
"price":1212,
"business":1
}
The issue here is that you are posting a list to BundleProduct
's product field yet it is an ForeignKey
. To join Bundle
to a Product
, simply POST
:
{
"bundle": 2,
"product" 1,
"number": 1
}
You can repeat this:
{
"bundle": 2,
"product" 4,
"number": 1
}
to add yet another product 4 to the same bundle and so on. Just make sure you do them one by one and not in a list as you had done earlier.