Working with M2M Intermediary Models
In this article, we will learn how to use through for Django many-to-many relationship. A few times in the last month, I’ve run into the need to add some metadata to a Django many-to-many relationship.
Let’s go through an example the existing models:
Create a model that matches the existing through table and using Meta.db_table:
Now, we change the many-to-many relationship to use the new model:
Now generate a new migration with python manage.py makemigrations. Then we will change it.
The initial migration
:
We just need to wrap these operations in migrations.SeparateDatabaseAndState to get the models in sync without screwing up the existing database setup. All of the changes above represent state changes:
Now you can add fields and create additional migrations as normal.
Admin
Admin should look like this:
Filtering on through fields
You should be able to filter on the through table fields by using the lowercase name of the through model.
# querysets
Group.objects.filter(membership__invite_reason="foo")
<QuerySet [<Group: Python>]>
Group.objects.filter(membership__invite_reason="bar")
<QuerySet [<Group: Django>]>
Person.objects.filter(membership__invite_reason="foo")
<QuerySet [<Person: Erdi>]>
Person.objects.filter(membership__invite_reason="bar")
<QuerySet [<Person: Erdi>]>
Membership.objects.filter(invite_reason='foo')
<QuerySet [<Membership: Erdi Python>]>
Membership.objects.filter(invite_reason='bar')
<QuerySet [<Membership: Erdi Django>]>
# related manager on instances
person_instance = Person.objects.first()
person_instance.groups.filter(membership__invite_reason='foo')
<QuerySet [<Group: Python>]>
group_instance = Group.objects.first()
group_instance.members.filter(membership__invite_reason='foo')
<QuerySet [<Person: Erdi>]>
In this article you’ve learned how to use a through with many-to-many relationship. If you want to see more information on through, you can visit this.