| 979 | Extra data on many-to-many relationships |
| 980 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 981 | |
| 982 | When you're only dealing with mixing and matching pizzas and toppings, a standard |
| 983 | ``ManyToManyField`` works great. For many situations, however, some extra data |
| 984 | is necessary about relationships between models. For situations like this, |
| 985 | Django allows for the specification of an intermediary many-to-many model. To |
| 986 | use this functionality, specify a ``through`` keyword argument onto the |
| 987 | ``ManyToManyField``. This is best illustrated with an example:: |
| 988 | |
| 989 | class Person(models.Model): |
| 990 | # ... |
| 991 | name = models.CharField(max_length=128) |
| 992 | |
| 993 | def __unicode__(self): |
| 994 | return self.name |
| 995 | |
| 996 | class Group(models.Model): |
| 997 | # ... |
| 998 | name = models.CharField(max_length=128) |
| 999 | members = models.ManyToManyField(Person, through='Membership') |
| 1000 | |
| 1001 | def __unicode__(self): |
| 1002 | return self.name |
| 1003 | |
| 1004 | class Membership(models.Model): |
| 1005 | person = models.ForeignKey(Person) |
| 1006 | group = models.ForeignKey(Group) |
| 1007 | date_joined = models.DateTimeField() |
| 1008 | invite_reason = models.CharField(max_length=64) |
| 1009 | |
| 1010 | Now that you have set up your ``ManyToManyField`` to use your intermediary |
| 1011 | model (Membership, in this case), you're ready to use the convenience methods |
| 1012 | provided by that ``ManyToManyField``. Here's an example of how you can query |
| 1013 | for and use these models:: |
| 1014 | |
| 1015 | >>> ringo = Person.objects.create(name="Ringo Starr") |
| 1016 | >>> paul = Person.objects.create(name="Paul McCartney") |
| 1017 | >>> beatles = Group.objects.create(name="The Beatles") |
| 1018 | >>> m1 = Membership.objects.create(person=ringo, group=beatles, |
| 1019 | ... date_joined=datetime(1962, 8, 16), |
| 1020 | ... invite_reason= "Needed a new drummer.") |
| 1021 | >>> beatles.members.all() |
| 1022 | [<Person: Ringo Starr>] |
| 1023 | >>> ringo.group_set.all() |
| 1024 | [<Group: The Beatles>] |
| 1025 | >>> m2 = Membership.objects.create(person=paul, group=beatles, |
| 1026 | ... date_joined=datetime(1960, 8, 1), |
| 1027 | ... invite_reason= "Wanted to form a band.") |
| 1028 | >>> beatles.members.all() |
| 1029 | [<Person: Ringo Starr>, <Person: Paul McCartney>] |
| 1030 | |
| 1031 | As you can see, creating ``Membership`` objects automatically adds the |
| 1032 | ``Person`` objects to the ``beatles.members`` queryset. This means that you |
| 1033 | can do anyting that you would do on a normal queryset, like ``filter`` or |
| 1034 | ``exclude``. |
| 1035 | |
| 1036 | .. note:: |
| 1037 | |
| 1038 | As soon as an intermediary model is specified, the ``add`` and |
| 1039 | ``remove`` methods become unavailable on the descriptors added by the |
| 1040 | ``ManyToManyField``. For example, something like |
| 1041 | ``beatles.members.add(paul)`` will no longer work. |
| 1042 | |
| 1043 | For more examples and ideas on how to work with intermediary models, |
| 1044 | `see the tests`_. |
| 1045 | |
| 1046 | .. _`see the tests`: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/m2m_manual/models.py |
| 1047 | |