I have the following fields on my model:
class Range(models.Model):
optimal_low = models.DecimalField(max_digits=30, decimal_places=8)
optimal_high = models.DecimalField(max_digits=30, decimal_places=8)
And here's how I bring them into the form (because the form's primary object is not this model, I just need the fields, and don't want to duplicate the max_digits and decimal_places.
class ReadingMappingForm(forms.ModelForm):
optimal_low = Range._meta.get_field('optimal_low').formfield()
optimal_high = Range._meta.get_field('optimal_high').formfield()
It seems django allows entering of decimals in scientific notation out of the box, but there's a glitch above a certain threshold.
In the form, if I input 1.5E9 it works fine, and the value gets saved as 1500000000.00000000 (Here's an online scientific notation calculator ).
However if I input 1.5E10 it says:
Ensure that there are no more than 8 decimal places.
Which is wrong, because I'm not adding any decimal places. In fact, if I enter 1.5E10 in normal notation, even with the 8 decimal places added, ie 15000000000.00000000 it works fine.
So I think something is not working correctly under the hood...
EDIT
I tested the field in the console, and it errors there:
from django.forms import DecimalField
>>> f = DecimalField(max_digits=30, decimal_places=8)
>>> f.clean('1.5E9')
Decimal('1.5E+9')
>>> f.clean('1.5E10')
Traceback (most recent call last):
File "myproject/env/lib/python3.5/site-packages/django/core/management/commands/shell.py", line 69, in handle
self.run_shell(shell=options['interface'])
File "myproject/env/lib/python3.5/site-packages/django/core/management/commands/shell.py", line 61, in run_shell
raise ImportError
ImportError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "myproject/env/lib/python3.5/site-packages/django/forms/fields.py", line 168, in clean
self.run_validators(value)
File "myproject/env/lib/python3.5/site-packages/django/forms/fields.py", line 157, in run_validators
raise ValidationError(errors)
django.core.exceptions.ValidationError: ['Ensure that there are no more than 8 decimal places.']
It does seem to be bug in DecimalValidator with the following explanation
Number that you stated 1.5E10 is parsed as object with properties _int '15'
and _exp 9
In DecimalValidator __call__
method number of decimals is calculated as
decimals = abs(exponent)
which than furthermore triggers the following
if self.decimal_places is not None and decimals > self.decimal_places:
raise ValidationError(
self.messages['max_decimal_places'],
code='max_decimal_places',
params={'max': self.decimal_places},
)
Seems that fix for following would be something like
if exponent < 0:
decimal = abs(exponent)
else:
decimal = 0
Fix for version 2.0 looks like following
# If the absolute value of the negative exponent is larger than the # number of digits, then it's the same as the number of digits, # because it'll consume all of the digits in digit_tuple and then # add abs(exponent) - len(digit_tuple) leading zeros after the # decimal point. if abs(exponent) > len(digit_tuple): digits = decimals = abs(exponent) else: digits = len(digit_tuple) decimals = abs(exponent)
这是一个已知的错误,已修复,但据我所知仅在 django 2.0 中存在。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.