如何强制Django将默认的DecimalField格式的零转换为常规格式?

时间:2018-10-01 15:47:55

标签: django django-models decimal

我的一个模型中有一个很大的DecimalField。

class Price(models.Model):
    min_value = models.DecimalField(max_digits=50, decimal_places=20)

所以基本上,它的数量很大,可以存储多达20个精度点。

所有值似乎都起作用,而不是零。可以说我使用以下命令将该字段序列化为json对象:

import json
from django.core.serializers.json import DjangoJSONEncoder

price = Price.objects.get(pk=1)
json = json.loads(json.dumps({
    "min_value" : price.min_value,
}, cls=DjangoJSONEncoder))

对于大多数值,我以字符串格式获取正确的十进制数字。但是,如果将min_value设置为0,我将得到如下内容:"0E-20"

我很确定它的意思是0.00000000000000000000,或在该点之后的20个零。但是,我想以通常的格式,或者基本上是这样:"0.00000000000000000000"

如何强制DjangoJSONEncoder执行此操作?注意,我确实意识到我可以使用字符串“ 0E-20”轻松地做到这一点,方法是在破折号后加上数字,运行一次for循环多次,并生成仅包含零的字符串。但是,有没有更好,更优雅的解决方案?

1 个答案:

答案 0 :(得分:2)

Django的内置JSON编码器仅将Decimal对象强制转换为字符串,因此故障出在标准库。

>>> from decimal import Decimal
>>> x = Decimal('0.00000000000000000000')
>>> x
Decimal('0E-20')
>>> str(x)
'0E-20'
>>> '{:f}'.format(x)
'0.00000000000000000000'

通过快速测试,似乎可以将小数格式化为浮点数,因此请尝试使用此自定义编码器:

import decimal
from django.core.serializers.json import DjangoJSONEncoder

class CustomJSONEncoder(DjangoJSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return '{:f}'.format(o)
        return super().default(o)