Opened 10 years ago

Closed 10 years ago

#8050 closed (fixed)

DecimalField no longer takes float values

Reported by: Karen Tracey <kmtracey@…> Owned by: nobody
Component: Documentation Version: master
Severity: Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


As of r8143, given a model like this:

class Dec(models.Model):
    avg = models.DecimalField(decimal_places=2, max_digits=5)

I'm seeing failures like this:

>>> d1 = Dec(avg=2.3)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "d:\u\kmt\django\trunk\django\db\models\", line 274, in save
  File "d:\u\kmt\django\trunk\django\db\models\", line 330, in save_base
    values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)]
  File "d:\u\kmt\django\trunk\django\db\models\fields\", line 232, in get_db_prep_save
    return self.get_db_prep_value(value)
  File "d:\u\kmt\django\trunk\django\db\models\fields\", line 735, in get_db_prep_value
    return connection.ops.value_to_db_decimal(self.to_python(value),
  File "d:\u\kmt\django\trunk\django\db\models\fields\", line 709, in to_python
    return decimal.Decimal(value)
  File "d:\bin\Python2.5.1\lib\", line 578, in __new__
    "First convert the float to a string")
TypeError: Cannot convert float to Decimal.  First convert the float to a string

Prior to r8143 code like this worked fine. Now I realize it's called DecimalField, so perhaps I should be passing in a Decimal not a float, but when originally written this code (not the above but the code where I actually hit the problem) used a FloatField, and at some point I migrated it to DecimalField via these instructions:

which don't mention anywhere the need to migrate to passing in Decimals for the values. Is the intent to no longer allow passing floats here? If so it probably needs a mention in Backwards Incompatible Changes.

Change History (2)

comment:1 Changed 10 years ago by Malcolm Tredinnick

Component: Database wrapperDocumentation
Triage Stage: UnreviewedAccepted

I think you're right on all counts (except where you try to pass a float off as a decimal). The current code is better and actually catches this as a bug. And, yes, we need to add it to BackwardsIncompatibleChanges. I'll do that momentarily.

We shouldn't really try to fake the float -> decimal conversion because it really does lose precision (and would be inconsistent with how Python works). You can pass in strings or decimals there.

comment:2 Changed 10 years ago by Malcolm Tredinnick

Resolution: fixed
Status: newclosed

Done. Thanks, Karen.

Note: See TracTickets for help on using tickets.
Back to Top