Django model field for monetary amounts.
pip install django-moneyfield
Moneyfield requires:
- Python ==3.3
- Django ==1.5 (still working on 1.6 compatibility)
- Money
- Babel (if you need currency formatting)
The field price
will be created in the database as two columns: price_amount
, and price_currency
. You may use any name <fieldname>
, resulting in columns <fieldname>_amount
and <fieldname>_currency
.
The attribute price
is only a convenience python descriptor that accepts and returns Money objects, and will be available only when working with a model instance.
For any operation using Managers and QuerySets, the amount and the currency must be addressed separately, using price_amount
and price_currency
in this case. This allows for maximum flexibility and unambiguity.
new_book = Book.objects.create(
name="The new book",
price_amount=Decimal("29.99"),
price_currency="USD"
)
books_in_usd = Book.objects.filter(price_currency="USD")
cheap_books = Book.objects.filter(price_amount__lt=Decimal('2'))
cheap_books_eur = Book.objects.filter(
price_amount__lt=Decimal('2'),
price_currency="EUR"
)
You can provide separate defaults for the amount and the currency as Decimal and the three letter currency code string, respectively:
or a default Money value:
You can also set currency choices with currency_choices
and a currency default with currency_default
:
If you don't need to handle different currencies but want to benefit from using the Money class instead of just Decimals, you may want to set a fixed currency for your monetary field:
In this case, the attribute price
will only accept and return Money objects with currency "USD". The database representation of this field will be price_amount
, with no currency column. This is consistent with the multi-currency case, and allows for maximum flexibility while making schema migrations.
- MoneyField.max_digits
Same as DecimalField: The maximum number of digits allowed in the number. Note that this number must be greater than or equal to
decimal_places
.- MoneyField.decimal_places
Same as DecimalField: The number of decimal places to store with the number.
- MoneyField.currency
Fixed currency for this field. This will omit the creation of a
<fieldname>_currency
column in the database.- MoneyField.default
Default Money value for this field (both amount and currency).
- MoneyField.currency_default
Default currency value.
- MoneyField.amount_default
Default amount value.
- MoneyField.currency_choices
Regular Django choices iterable, e.g.:
CURRENCY_CHOICES = ( ('EUR', 'Euros'), ('USD', 'US Dollars') )
A base model form class MoneyModelForm
is included to show the monetary fields as just one field in forms, instead of separate amount and currency fields.
Using MoneyModelForm
is optional. You may also include it in the base classes of your custom model form class.
There is already an excellent, mature, and stable package to handle money in Django: django-money.
The main difference in django-moneyfield is that the amount and currency are always created in the database as <fieldname>_amount
and <fieldname>_currency
, exposed in the same way in the model (alongside <fieldname>
, which returns Money
), and used in the same way while making queries.
This approach leads to a much simpler "model side" implementation, including efortless South compatibility. On the other hand, it makes the "modelform side" more complicated, as the user´s model field <fieldname>
is not really a model Field
.
For users of the package, this means making queries over separate fields <fieldname>_amount
and <fieldname>_currency
, which is more explicit and prevents further dependency on the package.
django-moneyfield also introduces the idea of a "fixed currency" mode, in which a currency column is not needed.
It is also designed with a Money class implementation of the same author in mind (probably compatible with other implementations, but untested).
Contributions are welcome. You can use the regular github mechanisms.
To run the tests, sit on the package root (by setup.py) and run:
python tests/runtests.py
django-moneyfield is released under the MIT license, which can be found in the file LICENSE
.