Opened 10 years ago
Last modified 12 months ago
#26459 assigned New feature
Allow providing DecimalField with a custom context
| Reported by: | yasondinalt | Owned by: | Daniel Rios |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.9 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
DecimalField has weird behavior in case of float values passed to field.
If decimal_places = 1
float 2.15 will be saved as 2.1 (!)
float 2.25 will be saved as 2.2 (!)
But if float value first converted to str:
float 2.15 will be saved as 0.2 (ok)
float 2.25 will be saved as 0.2 (!)
It's because of default decimal rounding ROUND_HALF_EVEN.
As I understand build-in round() use rounding similar to ROUND_HALF_UP.
I tried first cast float to str, then use ROUND_HALF_UP, so now:
float 2.15 will be saved as 0.2 (ok)
float 2.25 will be saved as 0.3 (ok)
Attachments (2)
Change History (10)
comment:1 by , 10 years ago
| Needs tests: | set |
|---|
by , 10 years ago
| Attachment: | 0001-tests-format-float-to-Decimal-with-proper-rounding.patch added |
|---|
follow-up: 3 comment:2 by , 10 years ago
Could you give a snippet of the application code where you run into this issue?
comment:3 by , 10 years ago
Replying to timgraham:
Could you give a snippet of the application code where you run into this issue?
class Invoice(models.Model):
# same as django-paypal use
mc_gross = models.DecimalField(max_digits=64, decimal_places=2, default=0)
invoice = 2.215 # float
invoice.save()
In DB will be value 2.21 (or if 2.225 -> 2.22)
by , 10 years ago
| Attachment: | 0001-DecimalField-rounding-first-cast-to-str-then-use-ROU.patch added |
|---|
Changes
comment:4 by , 10 years ago
| Needs tests: | unset |
|---|
I'm not sure whether or not to accept the ticket so I asked for advice on the django-developers mailing list.
p.s. You don't need to attach patches on the ticket when you also send a pull request.
comment:5 by , 10 years ago
| Has patch: | unset |
|---|---|
| Summary: | DecimalField float rounding → Allow providing DecimalField with a custom context |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Bug → New feature |
Accepting per Aymeric's proposal on the mailing list:
Currently DecimalField accepts max_digits and decimal_places options. I think it should accept a decimal context and delegate all operations to that context.
I suggest the following behavior:
- start with the decimal context provided in a kwarg to
DecimalFieldor, if there is None, the current context returned bygetcontext(). - modify that context to take into account
max_digitsanddecimal_places - ask the context to perform whatever operations we need
comment:8 by , 12 months ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
Tests