Django-rest-framework: Большие числа с плавающей запятой неправильно проходят проверку DecimalField

Созданный на 5 авг. 2015  ·  4Комментарии  ·  Источник: encode/django-rest-framework

Более крупные числа с плавающей запятой не проходят проверку DecimalField .

Например:

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

Я ожидал, что будет поднят ValidationError , поскольку это число состоит из более чем трех цифр. Проверка формы 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 рейтинги