Type error to create and update my list in django rest framework

后端 未结 3 1842
悲哀的现实
悲哀的现实 2021-01-17 01:57

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         


        
相关标签:
3条回答
  • 2021-01-17 02:40

    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

    0 讨论(0)
  • 2021-01-17 02:41

    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

    • override to_representation to return always List of ProdutSerializer Data
    • Override create for POST request
    • Override update for PUT and PATCH Request

    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
    
    }
    
    0 讨论(0)
  • 2021-01-17 02:43

    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.

    0 讨论(0)
提交回复
热议问题