【发布时间】:2020-10-26 21:40:14
【问题描述】:
: purchased_products = validated_data.pop("products") KeyError: 'products'
我在产品和购买之间存在 M2M 关系。我想要实现的是在进行购买时,也填充 PurchasedProduct(通过模型)模型。但是每次我将数据发送到 API 并尝试从 valid_data 访问序列化程序中的 products 键时,都会引发 keyError 异常,但如果我返回 valid_data 以调试 product 键是回应。
djangorestframework==3.11.0
django==2.2.10
class Product(Model):
name = CharField(max_length=20, unique=True)
date_added = DateTimeField(default=now)
models.py
class Purchase(Model):
manager = ForeignKey('users.User', on_delete=PROTECT, related_name='purchases')
quantity = DecimalField(max_digits=6, decimal_places=2)
products = ManyToManyField('branches.Product', through='PurchasedProduct',
through_fields=('purchase', 'product'))
amount_fc = IntegerField(default=0)
amount_usd = IntegerField(default=0)
total_amount = IntegerField(default=0)
date_purchased = DateTimeField(default=now)
class PurchasedProduct(Model):
purchase = ForeignKey('Purchase', on_delete=CASCADE, related_name="to_products", blank=True)
product = ForeignKey('branches.Product', on_delete=CASCADE, related_name='purchases')
unit_price = DecimalField(max_digits=12, decimal_places=4, default=0.00)
quantity = DecimalField(max_digits=5, decimal_places=2)
amount_fc = DecimalField(max_digits=10, decimal_places=2)
date_purchased = DateTimeField(default=now)
serializer.py
class PurchasedProductSerializer(ModelSerializer):
class Meta:
model = PurchasedProduct
fields = [
"id",
"purchase",
"product",
"unit_price",
"quantity",
"amount_fc",
"date_purchased"
]
class PurchaseSerializer(ModelSerializer):
# https://github.com/encode/django-rest-framework/issues/5403
products = PurchasedProductSerializer(source="to_products", many=True)
class Meta:
model = Purchase
fields = [
"id",
"manager",
"quantity",
"amount_fc",
"amount_usd",
"total_amount",
"products",
"date_purchased"
]
def create(self, validated_data):
purchased_products = validated_data.pop("products")
manager = validated_data.pop('manager')
quantity = validated_data.pop('quantity')
amount_fc = validated_data.pop('amount_fc')
amount_usd = validated_data.pop('amount_usd')
total_amount = validated_data.pop('total_amount')
purchase = Purchase.objects.create(
manager=manager,
quantity=quantity,
amount_fc=amount_fc,
amount_usd=amount_usd,
total_amount=total_amount
)
for purchased_product in purchased_products:
product = Product.objects.get(pk=purchased_product.pop("product"))
purchase.products.add(product, through_default=purchased_product)
return purchase
view.py
class PurchasesListView(ListCreateAPIView):
queryset = Purchase.objects.all()
serializer_class = PurchaseSerializer
permission_classes = [AllowAny]
filterset_fields = ['date_purchased', 'manager']
数据
{
"amount_fc": 13303340.0,
"amount_usd": 1500,
"manager": 2,
"quantity": 100,
"total_amount": 1230945,
"products": [
{
"amount_fc": 1200334,
"product": 8,
"quantity": 120,
"unit_price": 10003.34
},
{
"amount_fc": 1600334,
"product": 6,
"quantity": 100,
"unit_price": 16003.34
}
]
}
错误:
purchased_products = validated_data.pop("products") KeyError: 'products'
但是当我将purchased_products = validated_data.pop("products") 更改为purchased_products = validated_data.pop("products", []) 时,它可以工作,但不能填充直通模型(PurchasedProduct)
我的尝试
DRF 示例 DRF doc exampe
drf 可写嵌套 drf-writable-nested 不支持直通模式的M2M
删除源
products = PurchasedProductSerializer(many=True) 添加了 write_only=True read_only=False。我也尝试抑制 Product 模型上的 uniqueValidator,但仍然无法正常工作。
【问题讨论】:
-
为什么使用
pop()?但即使你使用get(),如果validate_data("products")不存在,你也会得到None。 -
完全正确。即使
.get()也不起作用。由于某些原因,当我发出POST请求时,它不包含在 valid_data 中,但GET可以正常工作
标签: python django django-rest-framework