I have three ideas about this.
1) In my opinion, assigning a float to a decimal field is a programming error. Sadly Python doesn’t raise an exception in that case.
>>> decimal.Decimal(2.15)
Decimal('2.149999999999999911182158029987476766109466552734375')
So Django has to support it as well.
2) Python 3 provides the `create_decimal_from_float(<float>)` class method on `decimal.Context` for this purpose. I think that’s what Django should use.
>>> decimal.Context(prec=10).create_decimal_from_float(2.15)
Decimal('2.150000000')
(I don’t care much about Python 2 at this point. We should just make sure we don’t introduce a debatable behavior in the last LTS release supporting Python 2.)
3) 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 DecimalField or, if there is None, the current context returned by `getcontext()`
- modify that context to take into account max_digits and decimal_places
- ask the context to perform whatever operations we need
I’m -1 on emulating that with arbitrary string conversions and rounding rules and also -1 on deviating from Python’s default behavior, which matches the IEEE 754 specification, without providing a way to customize that behavior properly.
I hope this helps !