输入错误以在Django Rest Framework中创建和更新我的列表 [英] Type error to create and update my list in 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屋!