输入错误以在Django Rest Framework中创建和更新我的列表 [英] Type error to create and update my list in django rest framework

查看:42
本文介绍了输入错误以在Django Rest Framework中创建和更新我的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用我的api来捆绑创建和更新产品。我是这样做的:

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_length=155)

class Product(models.Model):
    business = models.ForeignKey(
        Business,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )
    name = models.CharField(max_length=200)
    description = models.TextField(null=True, blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Product"



class Bundle(models.Model):
    business = models.ForeignKey(
        Business,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )
    name = models.CharField(max_length=100)
    description = models.TextField(null=True, blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    products = models.ManyToManyField(Product, related_name="bundles",blank=True, null=True, through="BundleProduct")

    class Meta:
        verbose_name = "Bundle"


    def __str__(self):
        return self.name

class BundleProduct(models.Model):

    bundle = models.ForeignKey(Bundle, on_delete=models.CASCADE, related_name="bundleproducts")
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="bundleproducts")
    number = models.IntegerField(default=1)

    class Meta:
        verbose_name = "Bundle of Product"


    def __str__(self):
        return str(self.product.name) + " do " + self.bundle.name

    def get_absolute_url(self):
        return reverse("BundleProduct_detail", kwargs={"pk": self.pk})

这是我的serializers.py:

And here is my serializers.py:

class ProductSerializer(serializers.ModelSerializer):

    class Meta:
        model = Product
        fields = "__all__"        

class BundleProductSerializer(serializers.ModelSerializer):

    class Meta:
        model = BundleProduct
        fields = "__all__"


class BundleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Bundle
        fields = "__all__"

我的viewset.py

My viewset.py

class ProductViewSet(viewsets.ModelViewSet):

    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    model = Product


class BundleProductViewSet(viewsets.ModelViewSet):

    queryset = BundleProduct.objects.all()
    serializer_class = BundleProductSerializer
    model = BundleProduct


class BundleViewSet(viewsets.ModelViewSet):

    queryset = Bundle.objects.all()
    serializer_class = BundleSerializer
    model = Bundle

当我尝试在bundleproducts中发布某些产品时,我收到错误的类型。预期的pk值,已收到列表。

When I try to post some products in bundleproducts I receive "Incorrect type. Expected pk value, received list."

在阅读此错误时,我发现了一些与PrimaryKeyRelatedField和SlugRelatedField有关的问题。我知道我需要重写,但我不知道如何

Reading about this error, I found some issues relating to PrimaryKeyRelatedField and SlugRelatedField. I know I need to override but I have no idea how to do it.

这是如何发布的示例:

{
    "number": 1,
    "bundle": 2,
    "product": 
         [
            1,
            2
         ]
}

在观看Neil评论的视频后,我创建了以下方法:

After watching the video commented by Neil, I created the following method:

class BundleSerializer(
    serializers.ModelSerializer
):
    products = ProductSerializer(many=True)

    def create(self, validated_data):
        products = validated_data.pop('products')
        bundle = BundleProduct.objects.create(**validated_data)
        for product in products:
            BundleProduct.objects.create(**product, bundle=bundle)
        return Bundle


    class Meta:
        model = Bundle
        fields = "__all__"

但不起作用。我收到此错误: / api / v1 / bundle /

But doesn't work. I receive this error: "TypeError at /api/v1/bundle/

'name'是此函数的无效关键字参数

'name' is an invalid keyword argument for this function"

推荐答案

如果您通过BundleSerializer进行发布,则需要传递带有ProductSerializer数据列表的产品,而不仅仅是id,因为BundleSerializer中的产品正在接受productsSerializer数据。您会收到类型错误'名称'是此函数的无效关键字参数 ,因为您的validated_data包含名称和BundleProduct对象没有名称字段。并且您正在使用validated_data创建BundleProduct对象。

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.

创建捆绑对象并将捆绑对象的ID传递给BundleProduct对象。

Create bundle object and pass id of bundle object to BundleProduct object.


  • 如果您不想创建产品而只传递现有的产品ID,则需要创建ListField

  • If you do not want to create product and just pass existing product id you need to make ListField

您需要覆盖 get_fields 并检查请求

下面是 POST 请求

对于 PATCH PUT 请求您需要替代ModelSerializer的更新方法并相应地处理产品。

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

将POST数据采样到BundleSerializer

sample POST data to BundleSerializer

{
    "products":[1,2],
    "name":"Offer One",
    "description":"description",
    "price":1212,
    "business":1

}

这篇关于输入错误以在Django Rest Framework中创建和更新我的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆