Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Created February 15, 2011 18:11
Show Gist options
  • Save jacobian/827937 to your computer and use it in GitHub Desktop.
Save jacobian/827937 to your computer and use it in GitHub Desktop.
An example of using many-to-many "through" to augment m2m relationships. See for context.
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=200)
groups = models.ManyToManyField('Group', through='GroupMember', related_name='people')
class Meta:
ordering = ['name']
def __unicode__(self):
class Group(models.Model):
name = models.CharField(max_length=200)
class Meta:
ordering = ['name']
def __unicode__(self):
class GroupMember(models.Model):
person = models.ForeignKey(Person, related_name='membership')
group = models.ForeignKey(Group, related_name='membership')
type = models.CharField(max_length=100)
def __unicode__(self):
return "%s is in group %s (as %s)" % (self.person,, self.type)
from django.test import TestCase
from .models import Person, Group, GroupMember
class M2MThroughTest(TestCase):
def setUp(self):
# Create three people:
self.joe = Person.objects.create(name='Joe')
self.jim = Person.objects.create(name='Jim')
self.bob = Person.objects.create(name='Bob')
# And three groups:
self.jocks = Group.objects.create(name='Jocks')
self.nerds = Group.objects.create(name='Nerds')
self.skaters = Group.objects.create(name='Skaters')
# Every person is a member of every group, but
# Joe admins jocks, Jim admins nerds, and Bob admins skaters.
GroupMember.objects.create(person=self.joe, group=self.jocks, type="admin")
GroupMember.objects.create(person=self.jim, group=self.jocks, type="member")
GroupMember.objects.create(person=self.bob, group=self.jocks, type="member")
GroupMember.objects.create(person=self.joe, group=self.nerds, type="member")
GroupMember.objects.create(person=self.jim, group=self.nerds, type="admin")
GroupMember.objects.create(person=self.bob, group=self.nerds, type="member")
GroupMember.objects.create(person=self.joe, group=self.skaters, type="member")
GroupMember.objects.create(person=self.jim, group=self.skaters, type="member")
GroupMember.objects.create(person=self.bob, group=self.skaters, type="admin")
def test_unfiltered_membership(self):
# Which groups is Jim in?
jims_groups = Group.objects.filter(people=self.jim)
self.assertEqual(list(jims_groups), [self.jocks, self.nerds, self.skaters])
def test_admin_groups(self):
# But which groups does Jim admin?
jim_admins = Group.objects.filter(people=self.jim, membership__type='admin')
self.assertEqual(list(jim_admins), [self.nerds])
def test_member_groups(self):
# And which groups is Bob just a member of?
bob_membership = Group.objects.filter(people=self.bob, membership__type='member')
self.assertEqual(list(bob_membership), [self.jocks, self.nerds])
Copy link

jlmitch5 commented Jun 9, 2014

Thanks for this...helped me easily write a fix with some weird foreign key reference issues.


Copy link

jlmitch5 commented Jun 9, 2014

Also, I think this is actually a bug...down to PR django if I'm not just being dumb. Check out that stackoverflow if you don't mind and let me know.

Copy link

how to query all Groups a person involved in ?
Also how to query All persons in a group ?

Copy link

@osjayaprakash try this
how to query all Groups a person involved in ?
R: having the person, use person.groups as the field is declared in model.
Also how to query All persons in a group ?
R: having the group, use group.people as the related_name define in ManyToMany field.

Copy link

Thanks for example!

Copy link

gives error. this code lacks more info.

Copy link

Very helpful, thanks for the example.

Copy link

Nine years later, still helpful. Thank you for this.

Copy link

Nice example! 👏🏻

Copy link


Copy link

Thanks, I was stuck!

Copy link

Nice Example~~
thank you for sharing

Copy link

Really helped me a lot. Thanks for sharing.

Copy link

Thanks for sharing. Very helpful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment