Opened 18 years ago
Closed 18 years ago
#2365 closed defect (fixed)
[patch] models.FloatField should be renamed
Reported by: | Owned by: | Adrian Holovaty | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | |
Severity: | normal | Keywords: | |
Cc: | rudolph.froger@…, gary.wilson@…, sergey.kirillov@…, andreas.eigenmann@…, nirvdrum@…, frederic.roland@…, waylan@…, adurdin@…, sandro@…, djangotrac@…, dan.fairs@…, simoncelen@…, dcramer@… | Triage Stage: | Design decision needed |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The behaviour of models.FloatField is inconsistent with its name. In the database backends it is implemented as a fixed-point NUMERIC column, and in Python it returns values of type decimal.Decimal -- which are compatible with each other, but are both incompatible with floating-point numbers. So it should be renamed to DecimalField or something similar that doesn't imply floating-point numbers.
Attachments (3)
Change History (30)
by , 18 years ago
Attachment: | DecimalField.diff added |
---|
comment:1 by , 18 years ago
Summary: | models.FloatField should be renamed → [patch] models.FloatField should be renamed |
---|
comment:2 by , 18 years ago
When you are using MySQL as your database backend, you get back Decimal instances for FloatField attributes like you described. But when your database backend is SQLite you get back normal python float numbers. I don't know what happens with PostreSQL
This is inconsistent behavior that should probably be addressed first.
comment:3 by , 18 years ago
There should definitely be a DecimalField that has nothing to do with floats -- probably also a FloatField for floating-point numbers, if there's a good use case for it.
by , 18 years ago
Attachment: | DecimalField-FloatField.diff added |
---|
Separate DecimalField and FloatField db and form fields
comment:4 by , 18 years ago
New patch: this creates a separate models.DecimalField and models.FloatField, and similar forms.DecimalField and forms.FloatField, and finally, validators.IsValidDecimal and validators.IsValidFloat.
Motivation for this separation comes from the fact that floats lack accuracy to represent decimals (e.g. for monetary values), and decimals are a bad match for floats (e.g. for values with large magnitude exponents). Following this motivation, IsValidDecimal does not accept numbers with a literal exponent, although IsValidFloat does.
This patch also modifies the MySQL and Sqlite database wrappers (I couldn't test against the others), to map DecimalField to NUMERIC, and FloatField to DOUBLE (MySQL) or NUMERIC (Sqlite, which means it's really a string, only collated as a number). The conversions table for MySQL is also changed so that DECIMAL and NEWDECIMAL fields are always returned as strings -- as the default behaviour is to return decimals if possible, or else floats; and we never want a float where we expected a decimal.
Finally, this patch should work without the decimal module: if the decimal module is available, then models.DecimalField attributes will be decimal.Decimal instances; if not, then they will be strings. If the user needs to perform arithmetic, then he can call float() and operate within the accuracy limits of floats, but it's safer not to convert implicitly.
comment:5 by , 18 years ago
I don't like the implication of the last paragraph of the previous comment. It means that every single time you do arithmetic with this field, you need to either test that you are running on Python 2.4 or call float(). This is a huge burden on the developer. It has to work a bit more transparently than that.
comment:6 by , 18 years ago
What about simply distribuite the module decimal.py
in django.utils
,
as we already do for, i.e., threading?
try: # Only exists in Python 2.4+ from decimal import Decimal except ImportError: # Import copy of _decimal.py from Python 2.4 from django.utils._decimal import Decimal
Decimal is just a single python file. See
http://www.taniquetil.com.ar/facundo/bdvfiles/get_decimal.html#downloading-the-files-separately
comment:7 by , 18 years ago
+1 on this. It would be more consistent to map NUMERIC
to decimal
than to float
. We should distribute decimal.py
to maintain compatibility with Python 2.3.
comment:8 by , 18 years ago
Cc: | added |
---|
comment:9 by , 18 years ago
Cc: | added |
---|
comment:11 by , 18 years ago
Cc: | added |
---|
+1 on this. A decimal type is very important for dealing with money.
comment:12 by , 18 years ago
+1 on
1) Renaming FloatField to DecimalField (and make it consistently Decimal across databases).
2) Creating a new FloatField that is indeed a floating point value (according to what databases provide).
I would say 1 is essential, 2 is nice to have.
comment:13 by , 18 years ago
Cc: | added |
---|
comment:14 by , 18 years ago
Cc: | added |
---|
comment:15 by , 18 years ago
Cc: | added |
---|
comment:16 by , 18 years ago
Cc: | added |
---|
by , 18 years ago
Attachment: | DecimalField-FloatField.2.diff added |
---|
Patch -- implements database FloatField and DecimalField, and supporting fields in oldforms and newforms, with tests.
comment:17 by , 18 years ago
Added an updated patch against r4439.
- db.FloatField handle only floats, and db.DecimalField handle only decimals.
- oldforms.FloatField and oldforms.DecimalField are the defaults for the db fields and do the Right Thing validation-wise
- newforms.FloatField and newforms.DecimalField ditto; but they also support max_value and min_value arguments à la newforms.IntegerField
This patch includes tests for both the database fields and the form fields.
comment:18 by , 18 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
Haven't heard from a core developer yet regarding this, so I'll leave it in their hands as to what we're going to do with this issue.
comment:19 by , 18 years ago
Cc: | added |
---|
comment:20 by , 18 years ago
Cc: | added |
---|
comment:21 by , 18 years ago
Cc: | added |
---|
comment:22 by , 18 years ago
Cc: | added |
---|
comment:24 by , 18 years ago
Cc: | added |
---|
comment:25 by , 18 years ago
- PostgreSql behavior seems to be analogous to that of MySQL. Using FloatField worked with SQLite for floating point values, but 'broke' (i.e., worked properly) when we tried to insert a floating point number into a NUMERIC field.
- SQLite behavior occurs because Sqlite puts whatever value it's passed into the database if it can't do a conversion to the defined type - field types in the table definitions are hints, but they are not strictly enforced. See http://www.sqlite.org/faq.html#q3. It's a feature.
- We are developing a system that requires the use of floating point numbers in the database. We probably have to use this patch (which is preferable to an ugly workaround) in order to move forward on our project.
comment:26 by , 18 years ago
Cc: | added |
---|
comment:27 by , 18 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
(In [5302]) Fixed #2365, #3324 -- Renamed FloatField to DecimalField and changed the code
to return Decimal instances in Python for this field. Backwards incompatible
change.
Added a real FloatField (stores floats in the database) and support for
FloatField and DecimalField in newforms (analogous to IntegerField).
Included decimal.py module (as django.utils._decimal) from Python 2.4. This is
license compatible with Django and included for Python 2.3 compatibility only.
Large portions of this work are based on patches from Andy Durdin and Jorge
Gajon.
Patch, also renames forms.FloatField (see #2366)