Django-rest-framework: Les flotteurs plus grands passent incorrectement la validation DecimalField

Créé le 5 août 2015  ·  4Commentaires  ·  Source: encode/django-rest-framework

Les plus gros flottants n'échouent pas DecimalField validation

Par exemple:

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

Je m'attendrais à ce qu'un ValidationError soit collecté puisque ce nombre a plus de 3 chiffres. La validation de formulaire de Django renvoie l'erreur attendue :

>>> 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 est généré si vous supprimez un zéro de l'exemple d'entrée ci-dessus :

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

De même, l'exception est également levée en utilisant le nombre d'origine mais sous la forme d'un Decimal et d'un 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.']

Une ligne de clé a récemment changé dans https://github.com/tomchristie/django-rest-framework/pull/2948 mais elle ne semble pas correcte et s'écarte de la validation forms.DecimalField de Django qui semble autrement avoir été copiée textuellement:

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

Je ne comprends pas vraiment le problème d'origine abordé dans #2948, donc je ne sais pas pourquoi la ligne a changé. Je suis plus qu'heureux de travailler sur le problème si je comprends le problème d'origine.

Vous trouverez ci-dessous un correctif avec un test raté :

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

Commentaire le plus utile

Maintenant résolu, avec une logique beaucoup plus transparente et évidente.

Tous les 4 commentaires

Merci Ryan.

Maintenant résolu, avec une logique beaucoup plus transparente et évidente.

@tomchristie @ryankask - Je vois que cela a été ajouté à un jalon de publication en 2015. Je rencontre toujours ce problème sur la version 3.11.0 . Le correctif a-t-il fini par être publié? Code ci-dessous :

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 vous obtenez l'erreur de validation attendue. Le groupe de discussion est le meilleur endroit pour prendre cette discussion et d'autres questions d'utilisation. Merci!

Cette page vous a été utile?
0 / 5 - 0 notes