Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example of using many-to-many "through" to augment m2m relationships. See http://www.quora.com/How-do-you-query-with-a-condition-on-a-ManyToMany-model-in-Django 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):
return self.name
class Group(models.Model):
name = models.CharField(max_length=200)
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name
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.group, 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])
@jlmitch5

This comment has been minimized.

Copy link

commented Jun 9, 2014

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

See: http://stackoverflow.com/questions/24127467/django-1-6-python-2-7-manytomany-not-mapping-references-to-joined-tables

@jlmitch5

This comment has been minimized.

Copy link

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.

@osjayaprakash

This comment has been minimized.

Copy link

commented May 20, 2015

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

@SamuelNata

This comment has been minimized.

Copy link

commented Aug 8, 2018

@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.

@Allan-Nava

This comment has been minimized.

Copy link

commented Sep 11, 2018

Thanks for example!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.