Более крупные числа с плавающей запятой не проходят проверку 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."])
)
Спасибо, Райан.
Теперь решено, с более прозрачной и очевидной логикой.
@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 вы получите ожидаемую ошибку проверки. Дискуссионная группа - лучшее место для обсуждения этого и других вопросов использования. Спасибо!
Самый полезный комментарий
Теперь решено, с более прозрачной и очевидной логикой.