我有一个案例,我很长一段时间都很好奇。说我有3个型号:
class Product(models.Model):
manufacturer = models.CharField(max_length=100)
description = models.TextField(blank=True)
class PurchasedProduct(models.Model):
product = models.ForeignKey(Product)
purchase = models.ForeignKey('Purchase')
quantity = models.PositiveIntegerField()
class Purchase(models.Model):
customer = models.ForeignKey('customers.Customer')
products = models.ManyToManyField(Product, through=PurchasedProduct)
comment = models.CharField(max_length=200)
我有一个用一些JavaScript框架编写的API和客户端应用程序。所以现在我需要在他们之间进行沟通!我不确定如何处理DRF中的这种情况,当然我希望在访问/purchase/1/
{
"id": 1,
"customer": 1,
"comment": "Foobar",
"products": [
{
"id": 1,
"product": {
"id": 1,
....
},
....
},
....
]
}
因此,我创建了正确的序列化程序,指定products
字段应使用PurchasedProductSerializer
,而ProductSerializer
依次使用嵌套的POST
。这很好,因为我得到所有必要的信息,比如显示购买的具体产品以及在购物期间使用适当的组件来说明React。
但是,当我需要PurchasedProduct
新{
"quantity": 10,
"purchase": 1,
"product": 1
}
时,问题就出现了。我希望最方便的形式是:
PurchasedProductSerializer
因为它包含所有必要的信息并且占地面积最小。但是,我无法使用product
来完成,因为它需要id
而不是GET
。
所以我的问题在这里,这是一个很好的方法(对我来说似乎很自然),我应该为POST
和var scale = ?
var originX = ?
var originY = ?
var rotation = ?
ctx.setTransform(scale,0,0,scale,originX,originY);
ctx.rotate(rotation);
使用两个单独的序列化器吗?我的表现应该不同吗?您能否指点一些最佳实践/书籍如何编写API和客户端应用程序?
答案 0 :(得分:1)
POST
请求它是最简单的占用空间最自然的方式。
为了正确处理POST
请求的数据,我最终使用了两个独立的Serializer,就像你描述的那样。如果您正在使用DRF视图集,则在GET
和POST
上选择正确序列化程序的一种方法是覆盖here所述的get_serializer_class
方法。
POST请求的反序列化器可能如下所示:
class PurchasedProductDeserializer(serializers.ModelSerializer):
product = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all())
purchase = serializers.PrimaryKeyRelatedField(queryset=Purchase.objects.all())
class Meta:
model = PurchasedProduct
fields = ('id', 'product', 'purchase', 'quantity')
write_only_fields = ('product', 'purchase', 'quantity')
然后可以将该反序列化器用于输入验证,最后将产品添加到购买中(或增加其数量)。
例如,在您的视图集中:
def create(self, request, *args, **kwargs):
# ...
# init your serializer here
serializer = self.get_serializer(data=request.data)
if serializer.is_valid(raise_exception=True):
# now check if the same item is already in the cart
try:
# try to find the product in the list of purchased products
purchased_product = serializer.validated_data['purchase'].purchasedproduct_set.get(product=serializer.validated_data['product'])
# if so, simply increase its quantity, else add the product as a new item to the cart (see except case)
purchased_product.quantity += serializer.validated_data['quantity']
purchased_product.save()
# update the serializer so it knows the id of the existing instance
serializer.instance = purchased_product
except PurchasedProduct.DoesNotExist:
# product is not yet part of the purchase cart, add it now
self.perform_create(serializer)
# ...
# do other stuff here
至于最佳做法,互联网上有大量文档可供使用,但如果您正在寻找书籍,您可能需要查看一些已发布的文章here。当你对REST感到厌倦时,你甚至可能想看看GraphQL。