英文:
Django rest framework post data not being serialized properly
问题
I have 2 models
class MenuItem(models.Model):
title = models.CharField(max_length=255, db_index=True)
price = models.DecimalField(max_digits=6, decimal_places=2, db_index=True)
featured = models.BooleanField(db_index=True)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
def __str__(self):
return f'{self.title}';
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
menuitem = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
quantity = models.SmallIntegerField()
unit_price = models.DecimalField(max_digits=6, decimal_places=2, default=0)
price = models.DecimalField(max_digits=6, decimal_places=2, default=0)
class Meta:
unique_together = ('menuitem', 'user')
The MenuItem.price should be equal to Cart.unit_price for a particular object. Now the problem I'm having is writing the serializer for the Cart Model.
So far I've tried this:
class MenuItemSerializer(serializers.HyperlinkedModelSerializer):
title = serializers.CharField(max_length=255)
price = serializers.DecimalField(max_digits=6, decimal_places=2)
category_id = serializers.IntegerField(write_only=True)
category = CategorySerializer(read_only=True)
featured = serializers.BooleanField()
class Meta:
model = MenuItem
fields = ['title', 'price', 'category', 'category_id', 'featured']
depth = 1
class CartSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault(),
)
menu_item = MenuItemSerializer
quantity = serializers.IntegerField()
# unit_price = serializers.DecimalField(max_digits=6, decimal_places=2, style={'input_type':'hidden'})
unit_price = serializers.ReadOnlyField(source="menuitem.price", read_only=True)
price = SerializerMethodField()
class Meta:
model = Cart
fields = ['user', 'menuitem', 'unit_price', 'quantity', 'price']
def get_price(self, obj):
return obj.quantity * obj.unit_price
and then the relevant view
class Cart(mixins.ListModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Cart.objects.all()
serializer_class = CartSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
However, this does not return the required value for price. It only returns 0.
I'm a Django newbie, and this has been driving me nuts. It would be nice if someone could help out.
This is an example response that I'm getting:
{
"menuitem": 1,
"unit_price": 2.5,
"quantity": 3,
"price": 0
}
英文:
I have 2 models
class MenuItem(models.Model):
title = models.CharField(max_length=255, db_index=True)
price = models.DecimalField(max_digits=6, decimal_places=2, db_index=True)
featured = models.BooleanField(db_index=True)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
def __str__(self):
return f'{self.title}'
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
menuitem = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
quantity = models.SmallIntegerField()
unit_price = models.DecimalField(max_digits=6, decimal_places=2, default=0)
price = models.DecimalField(max_digits=6, decimal_places=2, default=0)
class Meta:
unique_together = ('menuitem', 'user')
The MenuItem.price should be equal to Cart.unit_price for a particular object. Now the problem I'm having is writing the serializer for the Cart Model.
So far I've tried this:
class MenuItemSerializer(serializers.HyperlinkedModelSerializer):
title = serializers.CharField(max_length=255)
price = serializers.DecimalField(max_digits=6, decimal_places=2)
category_id = serializers.IntegerField(write_only=True)
category = CategorySerializer(read_only=True)
featured = serializers.BooleanField()
class Meta:
model = MenuItem
fields = ['title', 'price', 'category', 'category_id', 'featured']
depth = 1
class CartSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault(),
)
menu_item = MenuItemSerializer
quantity = serializers.IntegerField()
# unit_price = serializers.DecimalField(max_digits=6, decimal_places=2, style={'input_type':'hidden'})
unit_price = serializers.ReadOnlyField(source="menuitem.price", read_only=True)
price = SerializerMethodField()
class Meta:
model = Cart
fields = ['user', 'menuitem', 'unit_price', 'quantity', 'price']
def get_price(self, obj):
return obj.quantity * obj.unit_price
and then the relevant view
class Cart(mixins.ListModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Cart.objects.all()
serializer_class = CartSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
However this does not return the required value for price. It only returns 0.
I'm a django newbie and this has been driving me nuts. It would be nice if someone could help out.
This is an example response that I'm getting:
{
"menuitem": 1,
"unit_price": 2.5,
"quantity": 3,
"price": 0
}
答案1
得分: 0
你在Cart
模型中存储了price
和unit_price
,以及MenuItem
模型。
在CartSerializer
中,在get_price
方法内,你使用Cart
的unit_price
来计算最终价格,而不是使用MenuItem
的unit_price
,而CartSerializer
的unit_price
字段具有source="menuitem.price"
。
因此,在你分享的响应中,你从菜单项模型中得到了"unit_price": 2.5
,而你的价格是通过使用Cart
模型的unit_price
字段计算的,这个字段必须是0,因为它的默认值是0。因此,你的最终价格计算结果为3(数量)* 0(来自Cart模型的价格)= 0,而它应该是3(数量)* 2.5(来自MenuItem模型的价格)= 7.5。
确保从Cart
模型中删除多余的字段,以减少混淆,并更新CartSerializer中的get_price
方法如下:
def get_price(self, obj):
return obj.quantity * obj.menuitem.price
英文:
You are storing price
and unit_price
in the Cart
model along with the MenuItem
model.
In the CartSerializer
, inside the get_price
method, you are computing the final price by using the unit_price
of the Cart
, not the MenuItem
, while the unit_price
field of the CartSerializer
has source="menuitem.price"
.
So in the response you shared, you are getting "unit_price": 2.5
from the menu item model, while your price is being calculated by using the unit_price
field of Cart
model, which must be 0, as it defaults to 0. Hence, your final price results in 3 (quantity) * 0 (price from Cart model) = 0, while it should be 3 (quantity) * 2.5 (price from MenuItem model) = 7.5.
Make sure that you remove redundant fields from the Cart
model so it is less confusing, and update the get_price
method in the CartSerializer to:
def get_price(self, obj):
return obj.quantity * obj.menuitem.price
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论