Skip to content
Advertisement

Django – Create model with fields derivable from other model

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}'
Advertisement