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桁を超えているので、

>>> 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."])
     )
Bug

最も参考になるコメント

はるかに透過的で明白なロジックで解決されました。

全てのコメント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 評価