Django获取Serializer字段报value must be a decimal number错误如何解决?
错误原因
- 序列化器用法错误:DRF序列化器构造时,第一个入参是待序列化的模型实例,反序列化场景下必须显式指定
data=请求数据,你当前直接把请求数据作为第一个参数传入,属于用法错误。 - 未做数据校验:构造序列化器后没有调用
.is_valid()方法完成输入合法性校验,非法数据会直接进入后续逻辑。 - 字段取值错误:直接通过
serializer["字段名"]取到的是BoundField绑定字段对象,不是序列化器校验解析后的值,你将该对象传入模型要求Decimal类型的price字段,触发了类型不匹配的校验错误,报错信息中的<BoundField value=14.99 errors=None>就是你传入的对象的打印内容。
修复方案
基础修复(兼容现有service层写法)
修改视图层代码,调整序列化器用法,从校验后的validated_data中取字段值:
from rest_framework import status from rest_framework.response import Response @action(['POST'], detail=False, url_path='create_meal') def create_meal(self, *args, **kwargs): meal_data = self.request.data restaurant = Restaurant.objects.get(owner=self.request.user) # 反序列化场景显式指定data参数 serializer = MealSerializer(data=meal_data) # 校验数据,校验失败自动抛出400异常返回 serializer.is_valid(raise_exception=True) # 从validated_data取校验解析后的值 meal_create( title=serializer.validated_data["title"], description=serializer.validated_data["description"], price=serializer.validated_data["price"], restaurant=restaurant, slug=serializer.validated_data["slug"], discount=serializer.validated_data["discount"], ) return Response(status=status.HTTP_201_CREATED)
同时可以删除service.py中冗余的meal.save()调用,Meal.objects.create()已经完成了数据库写入操作,后续的save是重复执行无意义。
优化方案(减少冗余代码)
如果你的MealSerializer已经定义了所有需要的字段,直接调用序列化器的save方法即可完成数据创建,无需单独封装service层的创建方法:
from rest_framework import status from rest_framework.response import Response @action(['POST'], detail=False, url_path='create_meal') def create_meal(self, *args, **kwargs): meal_data = self.request.data serializer = MealSerializer(data=meal_data) serializer.is_valid(raise_exception=True) # 额外传入序列化器中未包含的restaurant参数 serializer.save(restaurant=Restaurant.objects.get(owner=self.request.user)) return Response(serializer.data, status=status.HTTP_201_CREATED)
内容的提问来源于stack exchange,提问作者nikitaex
相关产品推荐
相关产品推荐

