I am trying to create a custom field in Django which will take a decimal currency value (example: £1.56) and save it in the database as an Integer (example: 156) to store cu
Integer based MoneyField
I've been using this Django snippet for some time, but realized later it was introducing floating-point artifacts when converting to an integer before saving the the database.
Also, as of Django 1.9 SubfieldBase has been deprecated and we should use Field.from_db_value instead. So I've edited the code to fix both of these issues.
class CurrencyField(models.IntegerField):
description = "A field to save dollars as pennies (int) in db, but act like a float"
def get_db_prep_value(self, value, *args, **kwargs):
if value is None:
return None
return int(round(value * 100))
def to_python(self, value):
if value is None or isinstance(value, float):
return value
try:
return float(value) / 100
except (TypeError, ValueError):
raise ValidationError("This value must be an integer or a string represents an integer.")
def from_db_value(self, value, expression, connection, context):
return self.to_python(value)
def formfield(self, **kwargs):
from django.forms import FloatField
defaults = {'form_class': FloatField}
defaults.update(kwargs)
return super(CurrencyField, self).formfield(**defaults)