Code

Ticket #6095: docs.diff

File docs.diff, 3.5 KB (added by floguy, 7 years ago)

Added some (fairly extensive) documentation for this ticket. Please review it to make sure it's up to snuff. I'm not as good of a writer as I am a coder :)

Line 
1Index: docs/model-api.txt
2===================================================================
3--- docs/model-api.txt  (revision 6935)
4+++ docs/model-api.txt  (working copy)
5@@ -975,6 +975,71 @@
6                              name based upon the names of the two tables being joined.
7 
8     =======================  ============================================================
9+
10+Many-to-many relationships with an intermediary model
11+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12+
13+Sometimes many-to-many relationships require a bit more definition than a
14+standard ``ManyToManyField`` will allow.  For example, suppose that ``Topping``
15+object was pepperoni, and that you wanted to keep track of how many pepperoni
16+there were on each pizza.  In that case, Django allows for the specification of
17+an intermediary model -- Here's how that might look::
18+
19+    class Topping(models.Model):
20+        # ...
21+
22+    class Pizza(models.Model):
23+        # ...
24+        toppings = models.ManyToManyField(Topping, through='PizzaTopping')
25+   
26+    class PizzaTopping(models.Model):
27+        pizza = models.ForeignKey(Pizza)
28+        topping = models.ForeignKey(Topping)
29+        num_toppings = models.IntegerField(default=1)
30+
31+There are several things at play in this example.  The first thing to note is
32+that a new model has been created named ``PizzaTopping`` (in your own
33+applications, it can be named anything.  It need not be a concatenation of the
34+two related model names) which has two ``ForeignKey`` relationships:: one to
35+``Pizza``, and another to ``Topping``.
36+
37+The third field on our new ``PizzaTopping`` model is num_toppings, an
38+``IntegerField``.  This will be used to store information about how many of
39+each topping each pizza has.
40+
41+**NOTE:** Any extra fields on an intermediary model must either be nullable
42+(``null``=True), or have a default value.
43+
44+To complete this intermediary many-to-many definition, it is necessary to link
45+the intermediary model with the ``ManyToManyField``.  Doing so requires the use
46+of the ``through`` property on the ``ManyToManyField``.  This must be a string
47+representation of the intermediary model--in this case, ``PizzaTopping``.
48+
49+If you would like to specify a database table for the intermediary
50+relationship, setting the db_table property on a ``ManyToManyField`` will no
51+longer work correctly.  Instead, set the db_table property on the intermediary
52+model's inner ``Meta`` class.
53+
54+Now that you've got your intermediary model set up and you have it attached as
55+a ``ManyToManyField`` to Pizza, you can access the related data the same way as
56+normal.  ``Pizza`` model instances will now have access to related toppings
57+through the ``toppings`` attribute, and ``Topping`` model instances will now
58+have access to related pizzas through the ``pizza_set`` attribute.
59+
60+The additional information (in this case, num_toppings) is available by
61+accessing the intermediary model just like you would access any other model.
62+
63+Example::
64+   
65+    my_pizza = Pizza.objects.get(id=1)
66+    pepperoni = Topping.objects.get(id=1)
67+    pizza_topping = PizzaTopping.objects.get(pizza=my_pizza, topping=pepperoni)
68+    pizza_topping.num_toppings = 25
69+    pizza_topping.save()
70+   
71+For more examples on how to work with ``ManyToManyField``s, `see the tests`_.
72+
73+.. _see the tests: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/m2m_manual/models.py
74 
75 One-to-one relationships
76 ~~~~~~~~~~~~~~~~~~~~~~~~