Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary model association in Django

I've modeled a UML class Diagram like this

UML Diagram with ternary association

I want to translate this association to Django. I have the following:

class Crypto(models.Model):
    cryptoName = models.CharField(max_length=64, primary_key=True)

class Worker(models.Model):
    name = models.CharField(max_length=64)
    lastname = models.CharField(max_length=64)
    email = models.EmailField(max_length=128, primary_key=True)
    tlf = models.CharField(max_length=20)

    cryptos = models.ManyToManyField(Crypto)

class Operation(models.Model):
    refNum = models.IntegerField()
    datetime = models.DateTimeField()
    amount = models.FloatField()
    amountCrypto = models.FloatField()

I'm stuck at trying to represent the ternary association. Django has the through attr for ManyToManyField but, as you can see, the association is not m2m in any way, but mostly one-to-many. So how is the best way to represent this ternary association with Django models?


Edit: There will be cryptocurrencies registered in the database and what workers can do is enable using as many as they want (or disable, if it’s the case).

like image 374
oneberenjena Avatar asked Oct 19 '25 04:10

oneberenjena


1 Answers

If you want a worker has many cryptocurrencies. Then there are two use cases that will define what you must be using ManyToManyField or ForeignKey.

If cryptocurrency objects for all users are always different from one another.

For example, If the user is registering themselves and can create there own cryptocurrencies which are always different than already available currencies.

You must add a ForeignKey in your Crypto model instead of using ManyToManyField inside Worker model.

class Crypto(models.Model):
    cryptoName = models.CharField(max_length=64, primary_key=True)
    worker = models.ForeignKey(Worker, related_name='cryptos')

    def __str__(self):
       return self.cryptoName

Remove cryptos ManyToManyField relation from Worker model

In that way, you can have many cryptos related to a worker and you can access cryptos of a worker using the related_name mentioned in the field

worker = Worker.objects.first()
worker.cryptos
# output: <QuerySet [<Crypto: IOT>, <Crypto: BTC>, ...]>

If the user can choose from already available cryptocurrencies while Registering

That means multiple users are linking with the same object of crypto and a user can choose as many currencies.

You must use ManyToManyField as you are using now.

And you can simply access those currencies objects of a worker using

worker.cryptos
# output: <QuerySet [<Crypto: IOT>, <Crypto: BTC>, ...]>

For linking a cryptocurrency to a worker you can use .add()

crypto = Crypto.objects.get(cryptoName='BTC')
worker.cryptos.add(crypto)  

UPDATE

When you create ManyToManyField Relation, then behind the scene a table is created which keep the references of both models, But if you want to create your own middle table you have to use through keyword while defining ManyToManyField

class Worker(models.Model):
    ...
    # rest of the fields 
    cryptos = models.ManyToManyField(Crypto, through='Operation', related_name='workers')

and add the foreign key of both models manually to Operation model.

class Operation(models.Model):
    ...
    # rest of fields
    worker = models.ForeignKey(Worker, related_name='operation')
    crypto = models.ForeignKey(Crypto, related_name='operation')

Check out the official docs for more info on how to use it.

like image 190
Satendra Avatar answered Oct 20 '25 18:10

Satendra