Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: How should I store a money value?

I'm running into a paradigm problem here. I don't know whether I should store money as a Decimal(), or if I should store it as a string and convert it to a decimal myself. My reasoning is this:

PayPal requires 2 decimal places, so if I have a product that is 49 dollars even, PayPal wants to see 49.00 come across the wire. Django's DecimalField() doesn't set a decimal amount. It only stores a maximum decimal places amount. So, if you have 49 in there, and you have the field set to 2 decimal places, it'll still store it as 49. I know that Django is basically type casting when it deserializes back from the database into a Decimal (since Databases don't have decimal fields), so I'm not completely concerned with the speed issues as much as I am with the design issues of this problem. I want to do what's best for extensibility.

Or, better yet, does anyone know how to configure a django DecimalField() to always format with the TWO_PLACES formatting style.

like image 328
orokusaki Avatar asked Jan 06 '10 15:01

orokusaki


People also ask

How do I add a price field in Django?

Now Django does not have a built-in Price Field; however, a field which simulates money in Django can be easily created using the DecimalField. Django's DecimalField requires 2 parameters, one is max_digits and the other is decimal_places. max_digits is the total number of digits that is in the number specified.


1 Answers

You might want to use the .quantize() method. This will round a decimal value to a certain number of places, the argument you provide specifies the number of places:

>>> from decimal import Decimal >>> Decimal("12.234").quantize(Decimal("0.00")) Decimal("12.23") 

It can also take an argument to specify what rounding approach you want (different accounting systems might want different rounding). More info in the Python docs.

Below is a custom field that automatically produces the correct value. Note that this is only when it is retrieved from the database, and wont help you when you set it yourself (until you save it to the db and retrieve it again!).

from django.db import models from decimal import Decimal class CurrencyField(models.DecimalField):     __metaclass__ = models.SubfieldBase      def to_python(self, value):         try:            return super(CurrencyField, self).to_python(value).quantize(Decimal("0.01"))         except AttributeError:            return None 

[edit]

added __metaclass__, see Django: Why does this custom model field not behave as expected?

like image 121
Will Hardy Avatar answered Oct 12 '22 01:10

Will Hardy