How to bind multiple models to one ManyToManyField?

Viewed 2968

There are,for example, such classes:

class A(models.Model):
 id = models.CharField(max_length=256, primary_key=True)
 mtm = models.ManyToManyField(B, C, D)

class B(models.Model):
 id = models.CharField(max_length=256, primary_key=True)
class C(models.Model):
 id = models.CharField(max_length=256, primary_key=True)
class D(models.Model):
 id = models.CharField(max_length=256, primary_key=True)

I know the implementation class of the field And the wrong, did so to make it clearer. You need to have that model And had a relationship ManyToMany with models b,C,D. How can this be done? Is there a special field?

1 Answers

At the moment of writing, this is not possible. A ManyToManyField [Django-doc] has a positional to argument with:

class ManyToManyField(to, **options)

A many-to-many relationship. Requires a positional argument: the class to which the model is related, which works exactly the same as it does for ForeignKey, including recursive and lazy relationships.

It would also create some confusion: what should the mtm return for some_a.mtm.all()? All related B objects? Tuples of B, C and D objects? What should be the name of the reversed relations?

This however does not mean that you can not emulate such relation. You can make a model that acts like a relation. In fact if you define a ManyToManyField, Django will create a table that stores data from this relation.

So we can define such model like:

class ABCDRel(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE, related_name='mtm')
    b = models.ForeignKey(B, on_delete=models.CASCADE, related_name='mtm')
    c = models.ForeignKey(C, on_delete=models.CASCADE, related_name='mtm')
    d = models.ForeignKey(D, on_delete=models.CASCADE, related_name='mtm')

We can then for example obtain a QuerySet of all related ABCDRelations with:

some_a.mtm.all()

Or you can obtain a QuerySet of all related B objects through this relation with:

B.objects.filter(mtm__a=some_a)

The relation can contain extra data, but in essence thus stores "tuples" of how the objects of the models relate to each other.

This thus creates an entity-relation model that looks, more or less, like:

Entity-relation model of this modeling

Related