A classic example of a ManyToManyField (django 4.2 docs or SO) looks something like this:
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Why the asymmetry? We have this natural scheme where a Person can belong to Groups through a Membership and vice versa. So why does Person make no reference to this? Or, perhaps better phrased, why does the framework see fit to encourage us to state the relationship only on one side?
# No one writes this:
class Person(models.Model):
name = models.CharField(max_length=128)
groups = models.ManyToManyField(Group, through='Membership')