diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2008-02-22 01:05:05 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2008-02-22 01:05:05 +0000 |
| commit | 0c20e88e65b8c2b1d097510ee2d7cfe6b2cf9b97 (patch) | |
| tree | 14378fabc83fb32b4a23941a856c0c690ef4aa5a /docs | |
| parent | ca123b0760de38b4df50ca321927a365d2d1c796 (diff) | |
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
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/model-api.txt | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/docs/model-api.txt b/docs/model-api.txt index 6ca08ae4e5..2687c00d14 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -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 =================== |
