diff options
| author | Chinmoy Chakraborty <chinmoy12c@gmail.com> | 2021-08-21 20:57:15 +0530 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-09-28 13:57:45 +0200 |
| commit | 6f310417941182fda01f5276462ad8538d5f77d8 (patch) | |
| tree | fd8042c64a9c8b629e5a016faf4882aea4f4dc60 | |
| parent | a9479202d758b144136e67724b7780381c0fa09f (diff) | |
[4.0.x] Fixed #33033 -- Prevented models.DecimalField from accepting NaN values.
Backport of b7fd668b37341fc92d67c4854c4f244e10895c9b from main
| -rw-r--r-- | django/db/models/fields/__init__.py | 7 | ||||
| -rw-r--r-- | tests/model_fields/test_decimalfield.py | 8 |
2 files changed, 15 insertions, 0 deletions
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index e79f4acf6c..0e72a09e59 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -2,6 +2,7 @@ import collections.abc import copy import datetime import decimal +import math import operator import uuid import warnings @@ -1539,6 +1540,12 @@ class DecimalField(Field): if value is None: return value if isinstance(value, float): + if math.isnan(value): + raise exceptions.ValidationError( + self.error_messages['invalid'], + code='invalid', + params={'value': value}, + ) return self.context.create_decimal_from_float(value) try: return decimal.Decimal(value) diff --git a/tests/model_fields/test_decimalfield.py b/tests/model_fields/test_decimalfield.py index 2d96cfd437..ea06ab9fa2 100644 --- a/tests/model_fields/test_decimalfield.py +++ b/tests/model_fields/test_decimalfield.py @@ -1,3 +1,4 @@ +import math from decimal import Decimal from django.core import validators @@ -65,6 +66,13 @@ class DecimalFieldTests(TestCase): bd = BigD.objects.get(pk=bd.pk) self.assertEqual(bd.d, Decimal('12.9')) + def test_save_nan_invalid(self): + msg = '“nan” value must be a decimal number.' + with self.assertRaisesMessage(ValidationError, msg): + BigD.objects.create(d=float('nan')) + with self.assertRaisesMessage(ValidationError, msg): + BigD.objects.create(d=math.nan) + def test_fetch_from_db_without_float_rounding(self): big_decimal = BigD.objects.create(d=Decimal('.100000000000000000000000000005')) big_decimal.refresh_from_db() |
