diff options
Diffstat (limited to 'docs/model-api.txt')
| -rw-r--r-- | docs/model-api.txt | 278 |
1 files changed, 271 insertions, 7 deletions
diff --git a/docs/model-api.txt b/docs/model-api.txt index f73c5aadf7..4ed4ede97a 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -52,7 +52,7 @@ Some technical notes: * The name of the table, ``myapp_person``, is automatically derived from some model metadata but can be overridden. See `Table names`_ below. * An ``id`` field is added automatically, but this behavior can be - overriden. See `Automatic primary key fields`_ below. + overridden. See `Automatic primary key fields`_ below. * The ``CREATE TABLE`` SQL in this example is formatted using PostgreSQL syntax, but it's worth noting Django uses SQL tailored to the database backend specified in your `settings file`_. @@ -886,6 +886,10 @@ relationship should work. All are optional: `related objects documentation`_ for a full explanation and example. + If using this in an `abstract base class`_, be + sure to read the `extra notes`_ in that section + about ``related_name``. + ``to_field`` The field on the related object that the relation is to. By default, Django uses the primary key of the related object. @@ -893,6 +897,8 @@ relationship should work. All are optional: .. _`Database API reference`: ../db-api/ .. _related objects documentation: ../db-api/#related-objects +.. _abstract base class: `Abstract base classes`_ +.. _extra notes: `Be careful with related_name`_ Many-to-many relationships ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -988,9 +994,6 @@ the relationship should work. All are optional: One-to-one relationships ~~~~~~~~~~~~~~~~~~~~~~~~ -The semantics of one-to-one relationships will be changing soon, so we don't -recommend you use them. If that doesn't scare you away, keep reading. - To define a one-to-one relationship, use ``OneToOneField``. You use it just like any other ``Field`` type: by including it as a class attribute of your model. @@ -1012,9 +1015,26 @@ As with ``ForeignKey``, a relationship to self can be defined by using the string ``"self"`` instead of the model name; references to as-yet undefined models can be made by using a string containing the model name. -This ``OneToOneField`` will actually replace the primary key ``id`` field -(since one-to-one relations share the same primary key), and will be displayed -as a read-only field when you edit an object in the admin interface: +Finally, ``OneToOneField`` takes the following extra option: + + ======================= ============================================================ + Argument Description + ======================= ============================================================ + ``parent_link`` When ``True`` and used in a model inherited from + another model, indicates that this field should + be used as the link from the child back to the + parent. See `Model inheritance`_ for more + details. + + **New in Django development version** + + ======================= ============================================================ + +**New in Django development version:** ``OneToOneField`` classes used to +automatically become the primary key on a model. This is no longer true, +although you can manually pass in the ``primary_key`` attribute if you like. +Thus, it's now possible to have multiple fields of type ``OneToOneField`` on a +single model. See the `One-to-one relationship model example`_ for a full example. @@ -1048,6 +1068,14 @@ Model metadata is "anything that's not a field", such as ordering options, etc. Here's a list of all possible ``Meta`` options. No options are required. Adding ``class Meta`` to a model is completely optional. +``abstract`` +------------ + +**New in Django development version** + +When set to ``True``, denotes this model as an abstract base class. See +`Abstract base classes`_ for more details. Defaults to ``False``. + ``db_table`` ------------ @@ -1155,6 +1183,10 @@ together. It's used in the Django admin and is enforced at the database level (i.e., the appropriate ``UNIQUE`` statements are included in the ``CREATE TABLE`` statement). +All the fields specified in ``unique_together`` must be part of the current +model. If you are using `model inheritance`_, you cannot refer to fields from +any parent classes in ``unique_together``. + **New in Django development version** For convenience, unique_together can be a single list when dealing @@ -2041,6 +2073,238 @@ You can also prevent saving:: .. _database API docs: ../db-api/ +Model inheritance +================= + +**New in Django development version** + +Model inheritance in Django works almost identically to the way normal class +inheritance works in Python. The only decision you have to make is whether you +want the parent models to be models in their own right (with their own +database tables), or if the parents are just holders of common information +that will only be visible through the child models. + +Often, you will just want to use the parent class to hold information that you +don't want to have to type out for each child model. This class isn't going to +ever be used in isolation, so `abstract base classes`_ are what you're after. However, if you're subclassing an existing model (perhaps something from another application entirely), or want each model to have its own database table, `multi-table inheritance`_ is the way to go. + +Abstract base classes +--------------------- + +Abstract base classes are useful when you want to put some common information +into a number of other models. You write your base class and put +``abstract=True`` in the ``Meta`` class. This model will then not be used to +create any database table. Instead, when it is used as a base class for other +models, its fields will be added to those of the child class. It is an error +to have fields in the abstract base class with the same name as those in the +child (and Django will raise an exception). + +An example:: + + class CommonInfo(models.Model): + name = models.CharField(max_length=100) + age = models.PositiveIntegerField() + + class Meta: + abstract = True + + class Student(CommonInfo): + home_group = models.CharField(max_length=5) + +The ``Student`` model will have three fields: ``name``, ``age`` and +``home_group``. The ``CommonInfo`` model cannot be used as a normal Django +model, since it is an abstract base class. It does not generate a database +table or have a manager or anything like that. + +For many uses, this type of model inheritance will be exactly what you want. +It provides a way to factor out common information at the Python level, whilst +still only creating one database table per child model at the database level. + +``Meta`` inheritance +~~~~~~~~~~~~~~~~~~~~ + +When an abstract base class is created, Django makes any ``Meta`` inner class +you declared on the base class available as an attribute. If a child class +does not declared its own ``Meta`` class, it will inherit the parent's +``Meta``. If the child wants to extend the parent's ``Meta`` class, it can +subclass it. For example:: + + class CommonInfo(models.Model): + ... + class Meta: + abstract = True + ordering = ['name'] + + class Student(CommonInfo): + ... + class Meta(CommonInfo.Meta): + db_table = 'student_info' + +Django does make one adjustment to the ``Meta`` class of an abstract base +class: before installing the ``Meta`` attribute, it sets ``abstract=False``. +This means that children of abstract base classes don't automatically become +abstract classes themselves. Of course, you can make an abstract base class +that inherits from another abstract base class. You just need to remember to +explicitly set ``abstract=True`` each time. + +Some attributes won't make sense to include in the ``Meta`` class of an +abstract base class. For example, including ``db_table`` would mean that all +the child classes (the ones that don't specify their own ``Meta``) would use +the same database table, which is almost certainly not what you want. + +Be careful with ``related_name`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are using the ``related_name`` attribute on a ``ForeignKey`` or +``ManyToManyField``, you must always specify a *unique* reverse name for the +field. This would normally cause a problem in abstract base classes, since the +fields on this class are included into each of the child classes, with exactly +the same values for the attributes (including ``related_name``) each time. + +To work around this problem, when you are using ``related_name`` in an +abstract base class (only), part of the name should be the string +``'%(class)s'``. This is replaced by the lower-cased name of the child class +that the field is used in. Since each class has a different name, each related +name will end up being different. For example:: + + class Base(models.Model): + m2m = models.ManyToMany(OtherModel, related_name="%(class)s_related") + + class Meta: + abstract = True + + class ChildA(Base): + pass + + class ChildB(Base): + pass + +The reverse name of the ``ChildA.m2m`` field will be ``childa_related``, +whilst the reverse name of the ``ChildB.m2m`` field will be +``childb_related``. It is up to you how you use the ``'%(class)s'`` portion to +construct your related name, but if you forget to use it, Django will raise +errors when you validate your models (or run ``syncdb``). + +If you don't specify a ``related_name`` attribute for a field in an abstract +base class, the default reverse name will be the name of the child class +followed by ``'_set'``, just as it normally would be if you'd declared the field directly on the child class. For example, in the above code, if the ``related_name`` attribute was omitted, the reverse name for the ``m2m`` field would be ``childa_set`` in the ``ChildA`` case and ``childb_set`` for the ``ChildB`` field. + +Multi-table inheritance +----------------------- + +The second type of model inheritance supported by Django is when each model in +the hierarchy is a model all by itself. Each model corresponds to its own +database table and can be queried and created individually. The inheritance +relationship introduces links between the child model and each of its parents +(via an automatically created ``OneToOneField``). For example:: + + class Place(models.Model): + name = models.CharField(max_length=50) + address = models.CharField(max_length=80) + + class Restaurant(Place): + serves_hot_dogs = models.BooleanField() + serves_pizza = models.BooleanField() + +All of the fields of ``Place`` will also be available in ``Restaurant``, +although the data will reside in a different database table. So these are both +possible:: + + >>> Place.objects.filter(name="Bob's Cafe") + >>> Restaurant.objects.filter(name="Bob's Cafe") + +If you have a ``Place`` that is also a ``Restaurant``, you can get from the +``Place`` object to the ``Restaurant`` object by using the lower-case version +of the model name:: + + >>> p = Place.objects.filter(name="Bob's Cafe") + # If Bob's Cafe is a Restaurant object, this will give the child class: + >>> p.restaurant + <Restaurant: ...> + +However, if ``p`` in the above example was *not* a ``Restaurant`` (it had been +created directly as a ``Place`` object or was the parent of some other class), +referring to ``p.restaurant`` would give an error. + +``Meta`` and multi-table inheritance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the multi-table inheritance situation, it doesn't make sense for a child +class to inherit from its parent's ``Meta`` class. All the ``Meta`` options +have already been applied to the parent class and applying them again would +normally only lead to contradictory behaviour (this is in contrast with the +abstract base class case, where the base class doesn't exist in its own +right). + +So a child model does not have access to its parent's ``Meta`` class. However, +there are a few limited cases where the child inherits behaviour from the +parent: if the child does not specify an ``ordering`` attribute or a +``get_latest_by`` attribute, it will inherit these from its parent. + +If the parent has an ordering and you don't want the child to have any natural +ordering, you can explicitly set it to be empty:: + + class ChildModel(ParentModel): + ... + class Meta: + # Remove parent's ordering effect + ordering = [] + +Inheritance and reverse relations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Because multi-table inheritance uses an implicit ``OneToOneField`` to link the +child and the parent, it's possible to move from the parent down to the child, +as in the above example. However, this uses up the name that is the default +``related_name`` value for ``ForeignKey`` and ``ManyToManyField`` relations. +If you are putting those type of relations on a subclass of another model, you +**must** specify the ``related_name`` attribute on each such field. If you +forget, Django will raise an error when you run ``manage.py validate`` or try +to syncdb. + +For example, using the above ``Place`` class again, let's create another +subclass with a ``ManyToManyField``:: + + class Supplier(Place): + # Must specify related_name on all relations. + customers = models.ManyToManyField(Restaurant, + related_name='provider') + +For more information about reverse relations, refer to the `Database API +reference`_ . For now, just remember to run ``manage.py validate`` when +you're writing your models and pay attention to the error messages. + +Specifying the parent link field +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As mentioned, Django will automatically create a ``OneToOneField`` linking +your child class back any non-abstract parent models. If you want to control +the name of the attribute linking back to the parent, you can create your own +link field and pass it ``parent_link=True``. For example, to explicitly +specify the field that will link ``Supplier`` to ``Place`` in the above +example, you could write:: + + class Supplier(Place): + parent = models.OneToOneField(Place, parent_link=True) + ... + +Multiple inheritance +-------------------- + +Just as with Python's subclassing, it's possible for a Django model to inherit +from multiple parent models. Keep in mind that normal Python name resolution +rules apply. The first base class that a particular name appears in (e.g. +``Meta``) will be the one that is used. We stop searching once we find the +name once. This means that if multiple parents contain a ``Meta`` class, only +the first one is going to be used. All others will be ignored. + +Generally, you won't need to inherit from multiple parents. The main use-case +where this is useful is for ''mix-in'' classes: adding a particular extra +field or method to every class that inherits the mix-in. Try to keep your +inheritance hierarchies as simple and straightforward as possible so that you +won't have to struggle to work out where a particular piece of information is +coming from. + Models across files =================== |
