| 978 | |
| 979 | Many-to-many relationships with an intermediary model |
| 980 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 981 | |
| 982 | Sometimes many-to-many relationships require a bit more definition than a |
| 983 | standard ``ManyToManyField`` will allow. For example, suppose that ``Topping`` |
| 984 | object was pepperoni, and that you wanted to keep track of how many pepperoni |
| 985 | there were on each pizza. In that case, Django allows for the specification of |
| 986 | an intermediary model -- Here's how that might look:: |
| 987 | |
| 988 | class Topping(models.Model): |
| 989 | # ... |
| 990 | |
| 991 | class Pizza(models.Model): |
| 992 | # ... |
| 993 | toppings = models.ManyToManyField(Topping, through='PizzaTopping') |
| 994 | |
| 995 | class PizzaTopping(models.Model): |
| 996 | pizza = models.ForeignKey(Pizza) |
| 997 | topping = models.ForeignKey(Topping) |
| 998 | num_toppings = models.IntegerField(default=1) |
| 999 | |
| 1000 | There are several things at play in this example. The first thing to note is |
| 1001 | that a new model has been created named ``PizzaTopping`` (in your own |
| 1002 | applications, it can be named anything. It need not be a concatenation of the |
| 1003 | two related model names) which has two ``ForeignKey`` relationships:: one to |
| 1004 | ``Pizza``, and another to ``Topping``. |
| 1005 | |
| 1006 | The third field on our new ``PizzaTopping`` model is num_toppings, an |
| 1007 | ``IntegerField``. This will be used to store information about how many of |
| 1008 | each topping each pizza has. |
| 1009 | |
| 1010 | **NOTE:** Any extra fields on an intermediary model must either be nullable |
| 1011 | (``null``=True), or have a default value. |
| 1012 | |
| 1013 | To complete this intermediary many-to-many definition, it is necessary to link |
| 1014 | the intermediary model with the ``ManyToManyField``. Doing so requires the use |
| 1015 | of the ``through`` property on the ``ManyToManyField``. This must be a string |
| 1016 | representation of the intermediary model--in this case, ``PizzaTopping``. |
| 1017 | |
| 1018 | If you would like to specify a database table for the intermediary |
| 1019 | relationship, setting the db_table property on a ``ManyToManyField`` will no |
| 1020 | longer work correctly. Instead, set the db_table property on the intermediary |
| 1021 | model's inner ``Meta`` class. |
| 1022 | |
| 1023 | Now that you've got your intermediary model set up and you have it attached as |
| 1024 | a ``ManyToManyField`` to Pizza, you can access the related data the same way as |
| 1025 | normal. ``Pizza`` model instances will now have access to related toppings |
| 1026 | through the ``toppings`` attribute, and ``Topping`` model instances will now |
| 1027 | have access to related pizzas through the ``pizza_set`` attribute. |
| 1028 | |
| 1029 | The additional information (in this case, num_toppings) is available by |
| 1030 | accessing the intermediary model just like you would access any other model. |
| 1031 | |
| 1032 | Example:: |
| 1033 | |
| 1034 | my_pizza = Pizza.objects.get(id=1) |
| 1035 | pepperoni = Topping.objects.get(id=1) |
| 1036 | pizza_topping = PizzaTopping.objects.get(pizza=my_pizza, topping=pepperoni) |
| 1037 | pizza_topping.num_toppings = 25 |
| 1038 | pizza_topping.save() |
| 1039 | |
| 1040 | For more examples on how to work with ``ManyToManyField``s, `see the tests`_. |
| 1041 | |
| 1042 | .. _see the tests: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/m2m_manual/models.py |