Django-rest-framework: 较大的浮点数错误地通过了 DecimalField 验证

创建于 2015-08-05  ·  4评论  ·  资料来源: encode/django-rest-framework

较大的浮点数不会失败DecimalField验证。

例如:

>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(200000000000.0)
>>> Decimal('2E+11')

我希望ValidationError会增加,因为该数字超过 3 位。 Django 的表单验证抛出了预期的错误:

>>> forms.DecimalField(max_digits=3, decimal_places=1).clean(200000000000.0)
ValidationError: [u'Ensure that there are no more than 3 digits in total.']

如果从上述示例输入中删除零,则会引发ValidationError

>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(20000000000.0)
ValidationError: [u'Ensure that there are no more than 3 digits in total.']

同样,也使用原始数字引发异常,但作为Decimal和 int:

>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(200000000000)
ValidationError: [u'Ensure that there are no more than 3 digits in total.']
>>> serializers.DecimalField(max_digits=3, decimal_places=1).run_validation(Decimal('200000000000.0'))
ValidationError: [u'Ensure that there are no more than 3 digits in total.']

最近在https://github.com/tomchristie/django-rest-framework/pull/2948 中更改了一个关键行,但它似乎不正确并且偏离了 Django 的forms.DecimalField验证,否则它似乎已被复制逐字:

decimals = exponent * decimal.Decimal(-1) if exponent < 0 else 0

我不太明白#2948 中解决的原始问题,所以我不知道为什么这条线改变了。 如果我理解最初的问题,我很乐意解决这个问题。

下面是一个测试失败的补丁:

diff --git a/tests/test_fields.py b/tests/test_fields.py
index 0427873..cf41a5b 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -773,6 +773,7 @@ class TestDecimalField(FieldValues):
         (Decimal('Nan'), ["A valid number is required."]),
         (Decimal('Inf'), ["A valid number is required."]),
         ('12.345', ["Ensure that there are no more than 3 digits in total."]),
+        (200000000000.0, ["Ensure that there are no more than 3 digits in total."]),
         ('0.01', ["Ensure that there are no more than 1 decimal places."]),
         (123, ["Ensure that there are no more than 2 digits before the decimal point."])
     )

最有用的评论

现在解决了,有一些更透明和明显的逻辑。

所有4条评论

谢谢瑞安。

现在解决了,有一些更透明和明显的逻辑。

@tomchristie @ryankask - 我看到这被添加到 2015 年的发布里程碑中。我仍然在3.11.0版本上遇到这个问题。 修复程序最终发布了吗? 代码如下:

class RecommendationSerializer(serializers.Serializer):
    total_owed = serializers.DecimalField(decimal_places=2, max_digits=8, min_value='1.00',
                                          rounding=ROUND_DOWN)
    term_length = serializers.IntegerField(min_value=1)

    class Meta:
        fields = ['total_owed', 'term_length']


serializer = RecommendationSerializer(data={'total_owed': '12.333333333333333', 'term_length': 6})
serializer.is_valid(raise_exception=True)

>>> {"total_owed": ["Ensure that there are no more than 8 digits in total."]}

@Audace你得到预期的验证错误。 讨论组是进行此讨论和其他使用问题的最佳场所。 谢谢!

此页面是否有帮助?
0 / 5 - 0 等级