#20765 closed Bug (fixed)
HTML5 number input type not working for DecimalField with big decimal_places
Reported by: | Owned by: | Simon Charette | |
---|---|---|---|
Component: | Forms | Version: | 1.6-beta-1 |
Severity: | Normal | Keywords: | |
Cc: | Simon Charette | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
DecimalFiled's widget is a NumberInput with step attribute equal to 10-decimal_placecese. https://github.com/django/django/blob/stable/1.6.x/django/forms/fields.py#L374).
If decimal_places is too big(the exact value for big
should be found here http://www.w3.org/TR/2012/WD-html5-20121025/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values) the step value parses to 0, which is not valid (http://www.w3.org/TR/2012/WD-html5-20121025/common-input-element-attributes.html#attr-input-step). It is not good in itself, but it also causes surprising and unwanted behaviour.
For example in Google Chrome input with type="number" and step="0.0000000000000000000000000000001" accepts only integer values!
A possible fix is to add optional step
argument to DecimalField and, and if it is not provided just use "any".
Attachments (2)
Change History (18)
comment:1 by , 11 years ago
Cc: | added |
---|---|
Severity: | Normal → Release blocker |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 11 years ago
Do you know the exact value for big?
No, I'm not an IEEE 754 expert =(
We could attempt defaulting step to the current behavior when decimal_place < big and fallback to any just how
FloatField
does.
I think that step > 0.001 is anyway useless in general. May be just .setdefault("step", "any")
exactly as in FloatField? In the face of ambiguity, refuse the temptation to guess.
comment:3 by , 11 years ago
Severity: | Release blocker → Normal |
---|
It seems to work until 1-18.
IMHO the float parsing algorithm is quite unambiguous and the default step
attribute is still overridable. I think we should be safe assuming our step
generation mechanism works for decimal_places <= 18
.
comment:4 by , 11 years ago
the default step attribute is still overridable
Not really, look again at https://github.com/django/django/blob/stable/1.6.x/django/forms/fields.py#L374
Even if I do
answer = fields.DecimalField(max_digits=50, decimal_places=25, widget=NumberInput(attrs={"step": "any"}))
the step gets overriden.
comment:6 by , 11 years ago
setdefult
defenetelly should be there.
However I think that it's still worth to check that decimal_places <= 18 and use any
as a default otherwise(or just always use any
).
comment:7 by , 11 years ago
What's definitely a bug is that step
is not overridable.
As of the number of decimal places, it's browser-dependant, and I'm less enthousiast to do something about it.
comment:8 by , 11 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
I'll write a patch and fix tests for the setdefault
behavior.
comment:9 by , 11 years ago
I would be completely happy if I could override step
. But it's because I know that I have to override it. Let me try to convince you for the last time that guessing step is not a good idea. There will be three points.
- Suppose I know nothing about this issue and just wrote in one of my forms
number = fields.DecimalField(max_digits=50, decimal_places=25)
. I use firefox and the form is working OK in it. Moreover, tests are working too. However, very soon I get a bug report that it's impossible to use non-integer numbers in Chrome! So I have to look into the source of the page, notice suspiciousstep="0.0000000000000000000000000001"
, and find out that it is the reason of strange behaviour. Next, I have to look inside django's source, to find out, from where thisstep
emerges. And only then I realize that I need to override it.
- Current default can produce invalid html.
The step attribute, if specified, must either have a value that is a valid floating-point number that parses to a number that is greater than zero, or must have a value that is an ASCII case-insensitive match for the string "any".
- If I close my eyes, forget about everything in the universe and ask myself, "what is the most reasonable default for
step
?" I hear a voice whispering "any
".
Also, this issue can show more often than it seems. 10-18 is quit a little number, and it looks like most users won't use such a high precision. However, it is the DecimalField. And if someone is using a Decimal instead of Float, it means that he cares about high precision. So it's rather likely that he uses many decimal places. Also, python's default prec for decimals is 28 places!
by , 11 years ago
Attachment: | 0001-Fixed-20765-Avoid-setting-step-on-NumberInput-when-m.patch added |
---|
comment:10 by , 11 years ago
Has patch: | set |
---|
Added a patch that still sets step
as default for max_digits <= 18
and 'any'
in the other case.
comment:11 by , 11 years ago
This looks good. I can see only one very minor caveat. If decimal_places=0 then step is equal to any, while 1 seems more reasonable.
comment:12 by , 11 years ago
I think I've found a middleground. Parsing works flawlessly in exponential form. Submitting an updated patch.
by , 11 years ago
Attachment: | 0001-Fixed-20765-Use-exponential-form-to-set-step-attribu.patch added |
---|
comment:14 by , 11 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
RFC, but please either add a comment about the rationale or refer to this ticket. Thanks!
comment:15 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
We shouldn't add a
step
argument toDecimalField
since it only concern thewidget
.Do you know the exact value for
big
?We could attempt defaulting
step
to the current behavior whendecimal_place < big
and fallback toany
just how `FloatField` does.