I have 2 Django models representing the coin domain. The Coin has some properties and the trading Pair is based on those properties.
class Coin(models.Model): code = models.CharField(max_length=8, primary_key=True) name = models.CharField(max_length=32) class Pair(models.Model): code = models.CharField(max_length=16, primary_key=True) name = models.CharField(max_length=64) base_currency = models.ForeignKey(Coin, on_delete=models.CASCADE, null=False, related_name='base_currency') quote_currency = models.ForeignKey(Coin, on_delete=models.CASCADE, null=False, related_name='quote_currency')
Let’s add a couple of Coin instances:
first = Coin.objects.create(code="BTC", name="Bitcoin") second = Coin.objects.create(code="USD", name="United States Dollar")
and one Pair:
Pair.objects.create(code="BTCUSD", name="Bitcoin / United States Dollar", base_currency=first, quote_currency=second)
As you can see, code and name in the Pair model can be derived from code and name in the Coin model. To put it simple:
- Pair Code = First Coin Code + Second Coin Code
- Pair Name = First Coin Name + “/” + Second Coin Name
But, in this example I simply hardcoded those values and for sure this is not the best way to handle this situation. For example: what if in the Coin model I need to change the name of an instance? Then, I will have to manually update code and name in the Pair model, because this values are not properly binded from the Coin Model.
I believe Pair code/name must be binded/derived from the Coin model in some way.
Is there a way to do that in Django?
Advertisement
Answer
You might not need to store the name of your Pair
since it can be infered from the references from Pair.base_currency
and Pair.quote_currency
.
A property on the Pair
class should be enough:
class Pair(models.Model): base_currency = models.ForeignKey(Coin, on_delete=models.CASCADE, null=False, related_name='base_currency') quote_currency = models.ForeignKey(Coin, on_delete=models.CASCADE, null=False, related_name='quote_currency') @property def code(self) -> str: return self.base_currency.code + self.quote_currency.code @property def name(self) -> str: return f'{self.base_currency.name} / {self.quote_currency.name}'