使用序列化程序方法字段时,带有小数的字典将转换为整数。
例如。
class BillSerializer(serializers.ModelSerializer):
bill_details = serializers.SerializerMethodField()
class Meta:
model = Bill
fields = ('__all__')
def get_bill_details(obj):
return {'editable': False,
'final_amt': Decimal('4198.00'),
'total_amt': Decimal('4198.00'),
}
成为这个:
"bill_details": {
"total_amt": 4198,
"editable": false,
"final_amt": 4198
}
这有什么解决方案吗?我期待着这个:
"bill_details": {
"total_amt": "4198.00",
"editable": false,
"final_amt": "4198.00"
}
答案 0 :(得分:6)
Django REST Framework 3.0为您提供了以下选择
serialize decimals as floats
。
默认情况下,在序列化输出中,小数现在被强制为字符串。您可以使用COERCE_DECIMAL_TO_STRING
设置键来全局修改此行为。
REST_FRAMEWORK = {
'COERCE_DECIMAL_TO_STRING': False
}
或使用coerce_to_string
关键字参数在单个序列化器字段上对其进行修改。
# Return `Decimal` instances in `serializer.data`, not strings.
amount = serializers.DecimalField(
max_digits=10,
decimal_places=2,
coerce_to_string=False
)
默认的JSON渲染器将返回un-coerced
小数实例的float对象。这样一来,您就可以根据API设计的需要,轻松地在字符串或浮点数表示形式之间切换小数。
更新
如果只想四舍五入以产生2位小数精度的字符串以显示给用户,则可以
def get_bill_details(obj):
return {
'editable': False,
'final_amt': '%.2f' % Decimal('4198.00'),
'total_amt': '%.2f' % Decimal('4198.00'),
}
更新2
您可以使用自定义使其干燥 JSONEncoder 类。
创建一个DecimalEncoder
类,继承json.JSONEncoder
from decimal import Decimal
import json
class DecimalEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return '%.2f' % obj
return json.JSONEncoder.default(self, obj)
现在在get_bill_details
方法中使用此类
def get_bill_details(self, obj):
bill_detail = {
'editable': False,
'final_amt': Decimal('4198.00'),
'total_amt': Decimal('4198.00'),
}
return json.loads(json.dumps(bill_detail, cls=DecimalEncoder))
答案 1 :(得分:2)
您可以在SerializerMethodField中使用新的Serializer,如下所示:
from rest_framework import serializers
class BillDetailsSerializer(serializers.Serializer):
editable = serializers.BooleanField()
final_amt = serializers.DecimalField(decimal_places=2, max_digits=15)
total_amt = serializers.DecimalField(decimal_places=2, max_digits=15)
class BillSerializer(serializers.ModelSerializer):
bill_details = serializers.SerializerMethodField()
class Meta:
model = Bill
fields = '__all__'
def get_bill_details(self, obj):
data = {...} # your logic
field_serializer = BillDetailsSerializer(data=data)
field_serializer.is_valid() # this serializer must always valid
return field_serializer.data
我认为这更加清楚,每个人都可以理解哪些字段具有bill_details
答案 2 :(得分:1)
由于4198.00 == 4198
,如果要保留00
,则应使用str
如果您只喜欢在一个点后加上2个整数,则可以使用格式(例如hardi所说的format(obj.total_amt,'.2f')
,但结果应该是字符串(就像您在预期结果中所说的那样)
class BillSerializer(serializers.ModelSerializer):
bill_details = serializers.SerializerMethodField()
class Meta:
model = Bill
fields = ('__all__')
def get_bill_details(self, obj):
return {'editable': False,
'final_amt': str(Decimal('4198.00')),
'total_amt': str(Decimal('4198.00')),
}
答案 3 :(得分:1)
getItem
请尝试使用format()
答案 4 :(得分:0)
如果您不想对bill_details使用其他序列化器,那么</ p>
from rest_framework import serializers
from decimal import Decimal
class BillSerializer(serializers.ModelSerializer):
bill_details = serializers.SerializerMethodField()
class Meta:
model = Bill
fields = ('__all__')
def get_bill_details(obj):
amount_field = DecimalField(max_digits=12, decimal_places=2)
final_amt = Decimal('4198.00')
total_amt = Decimal('4198.00')
return {
'editable': False,
'final_amt': amount_field.to_representation(final_amt),
'total_amt': amount_field.to_representation(total_amt),
}