Reputation: 11
I have a Product model which has a price field and a currency field. the user can save different products using different currencies. some products are saved in usd, some in gbp, etc'..
class Product(models.Model):
price = models.DecimalField(
decimal_places=1,
max_digits=4,
default=0
)
usd = 'USD'
nis = 'NIS'
gbp = 'GBP'
CURRENCY_CHOICES = (
(usd , 'USD'),
(nis, 'NIS'),
(gbp, 'GBP')
)
currency = models.CharField(
max_length=3,
choices=CURRENCY_CHOICES,
default=usd,
blank=True
)
I want to be able to sort and view all of the products in a single currency.
how can i add a field, price_in_usd
, which will be set automatically when fields 'price' and 'currency' will be set?
something like this for example:
price_in_usd = convert_price_to_usd()
convert_price_to_usd():
if currency == GPB:
return price*1.25
if currency == NIS:
return price*0.33
Upvotes: 1
Views: 2897
Reputation: 1
You better use django-money which can handle money values including the conversion of currencies as shown below. *The code below converts USD
to EUR
:
# "views.py"
from django.http import HttpResponse
from app.models import Product
from djmoney.contrib.exchange.models import convert_money
from djmoney.money import Money
def test(request):
money = Product.objects.all()[0].price.amount
print(convert_money(Money(money, 'USD'), 'EUR')) # Here
return HttpResponse("Test")
You can see my answer and django-money doc which explain more about how to convert currencies.
Upvotes: 0
Reputation: 34972
You can use the clean()
method to handle this kind of behaviors.
class Product(models.Model):
price = models.DecimalField(decimal_places=1, max_digits=4, default=0)
currency = models.CharField(
max_length=3,
choices=CURRENCY_CHOICES,
default=usd,
blank=True
)
price_in_usd = models.DecimalField(decimal_places=1, max_digits=4, default=0, editable=False)
def clean(self):
if self.price and self.currency:
self.price_in_usd = convert_price_to_usd(self.price, self.currency)
See Django docs to know exactly when the clean()
method will be invoked. According to what you do, you may have to call explicitely full_clean()
yourself before calling save()
. Also clean()
won't be called if you use QuerySet.update()
or bulk_create()
for instance.
Another way to handle this might be to implement it at SQL level using triggers for instance.
However, if you want the price in USD to be updated (hourly, daily or whatever) to always match the current change rate, you will have to use a cron job to update price_in_usd
on a regular basis.
If you don't need to sort the data by price_in_usd
on the database level, another solution is to use a property:
class Product(models.Model):
price = models.DecimalField(decimal_places=1, max_digits=4, default=0)
currency = models.CharField(
max_length=3,
choices=CURRENCY_CHOICES,
default=usd,
blank=True
)
@property
def price_in_usd(self):
return convert_price_to_usd(self.price, self.currency)
Upvotes: 1