summaryrefslogtreecommitdiff
path: root/docs/model-api.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/model-api.txt')
-rw-r--r--docs/model-api.txt166
1 files changed, 155 insertions, 11 deletions
diff --git a/docs/model-api.txt b/docs/model-api.txt
index 4975953b97..93b27b8c11 100644
--- a/docs/model-api.txt
+++ b/docs/model-api.txt
@@ -112,7 +112,7 @@ class. Django uses the field class types to determine a few things:
* The widget to use in Django's admin interface, if you care to use it
(e.g. ``<input type="text">``, ``<select>``).
* The minimal validation requirements, used in Django's admin and in
- manipulators.
+ automatically-generated forms.
Here are all available field types:
@@ -144,10 +144,6 @@ The admin represents this as an ``<input type="text">`` (a single-line input).
(in characters) of the field. The max_length is enforced at the database level
and in Django's validation.
-Django veterans: Note that the argument is now called ``max_length`` to
-provide consistency throughout Django. There is full legacy support for
-the old ``maxlength`` argument, but ``max_length`` is preferred.
-
``CommaSeparatedIntegerField``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -641,9 +637,8 @@ callable it will be called every time a new object is created.
``editable``
~~~~~~~~~~~~
-If ``False``, the field will not be editable in the admin or via form
-processing using the object's ``AddManipulator`` or ``ChangeManipulator``
-classes. Default is ``True``.
+If ``False``, the field will not be editable in the admin or via forms
+automatically generated from the model class. Default is ``True``.
``help_text``
~~~~~~~~~~~~~
@@ -656,7 +651,10 @@ Note that this value is *not* HTML-escaped when it's displayed in the admin
interface. This lets you include HTML in ``help_text`` if you so desire. For
example::
- help_text="Please use the following format: <em>YYYY-MM-DD</em>."
+ help_text="Please use the following format: <em>YYYY-MM-DD</em>."
+
+Alternatively you can use plain text and
+``django.utils.html.escape()`` to escape any HTML special characters.
``primary_key``
~~~~~~~~~~~~~~~
@@ -716,7 +714,7 @@ that takes the parameters ``field_data, all_data`` and raises
Django comes with quite a few validators. They're in ``django.core.validators``.
-.. _validator docs: ../forms/#validators
+.. _validator docs: ../oldforms/#validators
Verbose field names
-------------------
@@ -942,6 +940,139 @@ the relationship should work. All are optional:
======================= ============================================================
+Extra fields on many-to-many relationships
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+When you're only dealing with simple many-to-many relationships such as
+mixing and matching pizzas and toppings, a standard ``ManyToManyField``
+is all you need. However, sometimes you may need to associate data with the
+relationship between two models.
+
+For example, consider the case of an application tracking the musical groups
+which musicians belong to. There is a many-to-many relationship between a person
+and the groups of which they are a member, so you could use a ManyToManyField
+to represent this relationship. However, there is a lot of detail about the
+membership that you might want to collect, such as the date at which the person
+joined the group.
+
+For these situations, Django allows you to specify the model that will be used
+to govern the many-to-many relationship. You can then put extra fields on the
+intermediate model. The intermediate model is associated with the
+``ManyToManyField`` using the ``through`` argument to point to the model
+that will act as an intermediary. For our musician example, the code would look
+something like this::
+
+ class Person(models.Model):
+ name = models.CharField(max_length=128)
+
+ def __unicode__(self):
+ return self.name
+
+ class Group(models.Model):
+ name = models.CharField(max_length=128)
+ members = models.ManyToManyField(Person, through='Membership')
+
+ def __unicode__(self):
+ return self.name
+
+ class Membership(models.Model):
+ person = models.ForeignKey(Person)
+ group = models.ForeignKey(Group)
+ date_joined = models.DateField()
+ invite_reason = models.CharField(max_length=64)
+
+When you set up the intermediary model, you explicitly specify foreign
+keys to the models that are involved in the ManyToMany relation. This
+explicit declaration defines how the two models are related.
+
+There are a few restrictions on the intermediate model:
+
+ * Your intermediate model must contain one - and *only* one - foreign key
+ on the target model (this would be ``Person`` in our example). If you
+ have more than one foreign key, a validation error will be raised.
+
+ * Your intermediate model must contain one - and *only* one - foreign key
+ on the source model (this would be ``Group`` in our example). If you
+ have more than one foreign key, a validation error will be raised.
+
+ * The only exception to this is a model which has a many-to-many
+ relationship to itself, through an intermediary model. In this
+ case, two foreign keys to the same model are permitted, but they
+ will be treated as the two (different) sides of the many-to-many
+ relation.
+
+ * When defining a many-to-many relationship from a model to
+ itself, using an intermediary model, you *must* use
+ ``symmetrical=False`` (see the documentation for
+ ``ManyToManyField`` above).
+
+Now that you have set up your ``ManyToManyField`` to use your intermediary
+model (Membership, in this case), you're ready to start creating some
+many-to-many relationships. You do this by creating instances of the
+intermediate model::
+
+ >>> ringo = Person.objects.create(name="Ringo Starr")
+ >>> paul = Person.objects.create(name="Paul McCartney")
+ >>> beatles = Group.objects.create(name="The Beatles")
+ >>> m1 = Membership(person=ringo, group=beatles,
+ ... date_joined=date(1962, 8, 16),
+ ... invite_reason= "Needed a new drummer.")
+ >>> m1.save()
+ >>> beatles.members.all()
+ [<Person: Ringo Starr>]
+ >>> ringo.group_set.all()
+ [<Group: The Beatles>]
+ >>> m2 = Membership.objects.create(person=paul, group=beatles,
+ ... date_joined=date(1960, 8, 1),
+ ... invite_reason= "Wanted to form a band.")
+ >>> beatles.members.all()
+ [<Person: Ringo Starr>, <Person: Paul McCartney>]
+
+Unlike normal many-to-many fields, you *can't* use ``add``, ``create``,
+or assignment (i.e., ``beatles.members = [...]``) to create relationships::
+
+ # THIS WILL NOT WORK
+ >>> beatles.members.add(john)
+ # NEITHER WILL THIS
+ >>> beatles.members.create(name="George Harrison")
+ # AND NEITHER WILL THIS
+ >>> beatles.members = [john, paul, ringo, george]
+
+Why? You can't just create a relationship between a Person and a Group - you
+need to specify all the detail for the relationship required by the
+Membership table. The simple ``add``, ``create`` and assignment calls
+don't provide a way to specify this extra detail. As a result, they are
+disabled for many-to-many relationships that use an intermediate model.
+The only way to create a many-to-many relationship with an intermediate table
+is to create instances of the intermediate model.
+
+The ``remove`` method is disabled for similar reasons. However, the
+``clear()`` method can be used to remove all many-to-many relationships
+for an instance::
+
+ # Beatles have broken up
+ >>> beatles.members.clear()
+
+Once you have established the many-to-many relationships by creating instances
+of your intermediate model, you can issue queries. Just as with normal
+many-to-many relationships, you can query using the attributes of the
+many-to-many-related model::
+
+ # Find all the groups with a member whose name starts with 'Paul'
+ >>> Groups.objects.filter(person__name__startswith='Paul')
+ [<Group: The Beatles>]
+
+As you are using an intermediate table, you can also query on the attributes
+of the intermediate model::
+
+ # Find all the members of the Beatles that joined after 1 Jan 1961
+ >>> Person.objects.filter(
+ ... group__name='The Beatles',
+ ... membership__date_joined__gt=date(1961,1,1))
+ [<Person: Ringo Starr]
+
One-to-one relationships
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1143,7 +1274,7 @@ any parent classes in ``unique_together``.
For convenience, unique_together can be a single list when dealing
with a single set of fields::
- unique_together = ("driver", "restaurant")
+ unique_together = ("driver", "restaurant")
``verbose_name``
----------------
@@ -1376,6 +1507,19 @@ good idea to be careful in your choice of default manager, in order to
avoid a situation where overriding of ``get_query_set()`` results in
an inability to retrieve objects you'd like to work with.
+Using managers for related object access
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default, Django uses a "bare" (i.e. default) manager when accessing related
+objects (i.e. ``choice.poll``). If this default isn't appropriate for your
+default manager, you can force Django to use a custom manager for related object
+attributes by giving it a ``use_for_related_fields`` property::
+
+ class MyManager(models.Manager)::
+ use_for_related_fields = True
+
+ ...
+
Model methods
=============