mirror of
https://github.com/django/django.git
synced 2025-10-28 08:06:09 +00:00
queryset-refactor: Fixed up and documented Meta-class inheritance.
Should be mostly logical (for versions of "logical" that may require you to be a Vulcan, admittedly, but that's not entirely my fault). git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7141 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
@@ -2031,6 +2031,18 @@ You can also prevent saving::
|
||||
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
|
||||
---------------------
|
||||
|
||||
@@ -2063,6 +2075,38 @@ 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.
|
||||
|
||||
Multi-table inheritance
|
||||
-----------------------
|
||||
|
||||
@@ -2100,8 +2144,29 @@ 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.
|
||||
|
||||
Normally you won't need to worry too much about how model inheritance works.
|
||||
It will behave similarly to Python class inheritance.
|
||||
``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 explicity set it to be empty::
|
||||
|
||||
class ChildModel(ParentModel):
|
||||
...
|
||||
class Meta:
|
||||
# Remove parent's ordering effect
|
||||
ordering = []
|
||||
|
||||
Inheritance and reverse relations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -2127,6 +2192,23 @@ 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.
|
||||
|
||||
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
|
||||
===================
|
||||
|
||||
|
||||
Reference in New Issue
Block a user