Django-rest-framework: Größere Floats bestehen fälschlicherweise die DecimalField-Validierung

Erstellt am 5. Aug. 2015  ·  4Kommentare  ·  Quelle: encode/django-rest-framework

Größere Floats scheitern nicht an der DecimalField Validierung.

Beispielsweise:

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

Ich würde erwarten, dass ein ValidationError ausgelöst wird, da diese Zahl mehr als 3 Stellen hat. Die Formularvalidierung von Django gibt den erwarteten Fehler aus:

>>> 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 wird ausgelöst, wenn Sie eine Null aus der obigen Beispieleingabe löschen:

>>> 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.']

In ähnlicher Weise wird die Ausnahme auch unter Verwendung der ursprünglichen Nummer ausgelöst, jedoch als Decimal und 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.']

Eine Schlüsselzeile wurde kürzlich in https://github.com/tomchristie/django-rest-framework/pull/2948 geändert, aber sie scheint nicht korrekt zu sein und weicht von Djangos forms.DecimalField Validierung ab, die ansonsten kopiert worden zu sein scheint wörtlich:

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

Ich verstehe das ursprüngliche Problem, das in #2948 angesprochen wurde, nicht wirklich, daher weiß ich nicht, warum sich die Zeile geändert hat. Ich bin mehr als glücklich, an dem Problem zu arbeiten, wenn ich das ursprüngliche Problem verstehe.

Unten ist ein Patch mit einem fehlgeschlagenen Test:

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

Hilfreichster Kommentar

Jetzt gelöst, mit einer viel transparenteren und offensichtlicheren Logik.

Alle 4 Kommentare

Danke Ryan.

Jetzt gelöst, mit einer viel transparenteren und offensichtlicheren Logik.

@tomchristie @ryankask - Ich sehe, dass dies bereits 2015 zu einem Release-Meilenstein hinzugefügt wurde. Ich stoße immer noch auf dieses Problem bei Version 3.11.0 . Wurde der Fix am Ende veröffentlicht? Code unten:

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 erhalten Sie den erwarteten Validierungsfehler. Die Diskussionsgruppe ist der beste Ort, um diese Diskussion und andere Nutzungsfragen zu führen. Vielen Dank!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen