Opened 7 years ago

Closed 7 years ago

#26189 closed Bug (invalid)

DecimalFields with float values raise errors on calling full_clean

Reported by: Leonard Kioi kinyanjui Owned by: nobody
Component: Database layer (models, ORM) Version: 1.9
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

After assigning a value with decimal places to a decimal field in a model , calling the model's full_clean method raises a ValidationError:

     ----> 1 transaction.full_clean()

/home/vagrant/.virtualenvs/cashbox/lib/python3.4/site-packages/django/db/models/base.py in full_clean(self, exclude, validate_unique)
   1134 
   1135         if errors:
-> 1136             raise ValidationError(errors)
   1137 
   1138     def clean_fields(self, exclude=None):

ValidationError: {'amount': ['Ensure that there are no more than 12 digits in total.']}

Seems to be raised by the new Decimal validator. Decimal field's to_python method creates a Decimal instance that has many decimal places which ends up violating the max_digits setting on the Decimal field.

Attachments (1)

models__piece.py (7.7 KB) - added by Leonard Kioi kinyanjui 7 years ago.

Download all attachments as: .zip

Change History (7)

comment:1 Changed 7 years ago by Leonard Kioi kinyanjui

Type: UncategorizedBug

comment:2 Changed 7 years ago by Tim Graham

Can you provide your model and the code to reproduce the issue?

Changed 7 years ago by Leonard Kioi kinyanjui

Attachment: models__piece.py added

comment:3 Changed 7 years ago by Leonard Kioi kinyanjui

I have added the relevant model in an attachment. The affected field is amount. Just creating a model instance and running full_clean on it raises a ValidationError. Error is raised even after saving. Here is an iPython session I ran:

  In [1]: user = User.objects.get(email='jeremy@gmail.com')                                                                                                                                                                          

In [2]: account = list(user.user_accounts.first())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-3e7c6aabfd88> in <module>()
----> 1 account = list(user.user_accounts.first())

TypeError: 'Account' object is not iterable

In [3]: account = user.user_accounts.first()                                                                                                                                                                                       

In [4]: currency = Currency.objects.first()

In [5]: transaction = Transaction(account=account, user=user, currency=currency, amount=34.22, date=timezone.now(), exchange_rate=ExchangeRate.objects.first())                                                                    

In [6]: transaction.full_clean()
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
<ipython-input-6-343b6af108cd> in <module>()
----> 1 transaction.full_clean()

/home/vagrant/.virtualenvs/cashbox/lib/python3.4/site-packages/django/db/models/base.py in full_clean(self, exclude, validate_unique)
   1134 
   1135         if errors:
-> 1136             raise ValidationError(errors)
   1137 
   1138     def clean_fields(self, exclude=None):

ValidationError: {'amount': ['Ensure that there are no more than 12 digits in total.']}

In [7]: transaction.save()

In [8]: transaction.full_clean()
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
<ipython-input-8-343b6af108cd> in <module>()
----> 1 transaction.full_clean()

/home/vagrant/.virtualenvs/cashbox/lib/python3.4/site-packages/django/db/models/base.py in full_clean(self, exclude, validate_unique)
   1134 
   1135         if errors:
-> 1136             raise ValidationError(errors)
   1137 
   1138     def clean_fields(self, exclude=None):

ValidationError: {'amount_primary': ['Ensure that there are no more than 12 digits in total.'], 'amount': ['Ensure that there are no more than 12 digits in total.']}
Last edited 7 years ago by Leonard Kioi kinyanjui (previous) (diff)

comment:4 Changed 7 years ago by Tim Graham

Do you have the problem if you change the default and amount from a float to Decimal, e.g. amount=decimal.Decimal('34.22'). This also came up in #25417.

comment:5 in reply to:  4 Changed 7 years ago by Leonard Kioi kinyanjui

Replying to timgraham:

Do you have the problem if you change the default and amount from a float to Decimal, e.g. amount=decimal.Decimal('34.22'). This also came up in #25417.

This solves the issue. Thanks.

comment:6 Changed 7 years ago by Tim Graham

Component: UncategorizedDatabase layer (models, ORM)
Resolution: invalid
Status: newclosed
Summary: Models with decimal fields raise errors on calling full_cleanDecimalFields with float values raise errors on calling full_clean
Note: See TracTickets for help on using tickets.
Back to Top