Django prices
Django fields for the prices module
django-prices: Django fields for the `prices` module ==================================================== The project is written primarily in Python, distributed under the BSD 3-Clause "New" or "Revised" License license, first published in 2012. Key topics include: currencies, currency, django, money, price.
django-prices: Django fields for the prices module
Installation
pip install django-prices- Add
django_pricesto yourINSTALLED_APPSatsettings.py
Features
Provides support for models:
pythonfrom django.db import models from django_prices.models import MoneyField, TaxedMoneyField class Model(models.Model): currency = models.CharField(max_length=3, default="BTC") price_net_amount = models.DecimalField(max_digits=9, decimal_places=2, default="5") price_net = MoneyField(amount_field="price_net_amount", currency_field="currency") price_gross_amount = models.DecimalField( max_digits=9, decimal_places=2, default="5" ) price_gross = MoneyField( amount_field="price_gross_amount", currency_field="currency" ) price = TaxedMoneyField( net_amount_field="price_net_amount", gross_amount_field="price_gross_amount", currency="currency", )
And forms:
pythonfrom django import forms from django_prices.forms import MoneyField AVAILABLE_CURRENCIES = ["BTC", "USD"] class ProductForm(forms.Form): name = forms.CharField(label="Name") price_net = MoneyField(label="net", available_currencies=AVAILABLE_CURRENCIES)
And validators:
pythonfrom django import forms from prices.forms import Money from django_prices.forms import MoneyField from django_prices.validators import ( MaxMoneyValidator, MinMoneyValidator, MoneyPrecisionValidator) class DonateForm(forms.Form): donator_name = forms.CharField(label="Your name") donation = MoneyField( label="net", available_currencies=["BTC", "USD"], max_digits=9, decimal_places=2, validators=[ MoneyPrecisionValidator(), MinMoneyValidator(Money(5, "USD")), MaxMoneyValidator(Money(500, "USD")), ], )
It also provides support for templates:
html{% load prices %} <p>Price: {{ foo.price.gross|amount }} ({{ foo.price.net|amount }} + {{ foo.price.tax|amount }} tax)</p>
You can also use HTML output from prices template tags, they will wrap currency symbol in a <span> element:
html{% load prices %} <p>Price: {{ foo.price.gross|amount:'html' }} ({{ foo.price.net|amount:'html' }} + {{ foo.price.tax|amount:'html' }} tax)</p>
It will be rendered as a following structure (for example with English locale):
html<span class="currency">$</span>15.00
How to migrate to django-prices 2.0
Version 2.0 introduces major changes to how prices data is stored in models, enabling setting price's currency per model instance.
Steps to migrate:
-
In your forms:
- remove the
currencyargument - add
available_currencieswith available choices.
If the form specified
MoneyFieldsinfieldsoption, replace those with explicit declarations instead:pythonAVAILABLE_CURRENCIES = [("BTC", "bitcoins"), ("USD", "US dollar")] class ModelForm(forms.ModelForm): class Meta: model = models.Model fields = [] price_net = MoneyField(available_currencies=AVAILABLE_CURRENCIES) - remove the
-
In your models using
MoneyField:-
Replace all occurrences of the
MoneyFieldclass withDecimalField -
Remove the
currencyargument from them -
Change
defaultfrom Money instance to value acceptable by Decimal fieldExample of code:
pythonprice_net = MoneyField( "net", currency="BTC", default=Money("5", "BTC"), max_digits=9, decimal_places=2 )Updated code:
pythonprice_net = models.DecimalField("net", default="5", max_digits=9, decimal_places=2)
-
-
In your migration files:
-
Replace all occurrences of the
MoneyFieldclass withDecimalField -
Remove the
currencyargument from them -
Change
defaultfrom Money instance to value acceptable by Decimal fieldpythonfield = django_prices.models.MoneyField(currency='BTC', decimal_places=2, default='5', max_digits=9, verbose_name='net')Updated code:
pythonfield = models.DecimalField(decimal_places=2, default='5', max_digits=9, verbose_name='net')
-
-
Rename fields in models. Your old field will still store amount of money, so probably the best choice would be
price_net_amountinsteadprice_net. -
All places which use Models and it's fields can prevent django app from even starting the code. Possible issues: code tries to access non existing fields. Exclude those fields for now from your ModelForms, Graphene types etc.
-
Run
python manage.py makemigrations. Make sure to do this step before adding newMoneyFieldsto model! If not, django will generatedelete/createmigrations instead ofrename. -
Run
python manage.py migrate. -
Update
django-prices. -
Add
models.CharFieldfor currency andMoneyFieldto your models:pythoncurrency = models.CharField(max_length=3, default="BTC") price_net_amount = models.DecimalField("net", default="5", max_digits=9, decimal_places=2) price_net = MoneyField(amount_field="price_net_amount", currency_field="currency") -
Run
python manage.py makemigrationsandpython manage.py migrate. -
Change
TaxedMoneyFielddeclaration:pythonprice = TaxedMoneyField( net_amount_field="price_net_amount", gross_amount_field="price_gross_amount", currency="currency", ) -
Remember to address changes in previously edited ModelForms
Crafted with ❤️ by Mirumee Software
Contributors
Showing top 12 contributors by commit count.
