1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

newforms-admin: Merged from trunk up to [7478]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7479 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Brian Rosner
2008-04-27 11:49:03 +00:00
parent 3f76c2a361
commit be9f09539c
69 changed files with 9647 additions and 3372 deletions

View File

@@ -160,37 +160,6 @@ When you save an object, Django performs the following steps:
is used to provide notification that an object has been successfully
saved. (These signals are not yet documented.)
Raw saves
~~~~~~~~~
**New in Django development version**
The pre-processing step (#2 in the previous section) is useful, but it modifies
the data stored in a field. This can cause problems if you're relying upon the
data you provide being used as-is.
For example, if you're setting up conditions for a test, you'll want the test
conditions to be repeatable. If pre-processing is performed, the data used
to specify test conditions may be modified, changing the conditions for the
test each time the test is run.
In cases such as this, you need to prevent pre-processing from being performed
when you save an object. To do this, you can invoke a **raw save** by passing
``raw=True`` as an argument to the ``save()`` method::
b4.save(raw=True) # Save object, but do no pre-processing
A raw save skips the usual data pre-processing that is performed during the
save. All other steps in the save (pre-save signal, data preparation, data
insertion, and post-save signal) are performed as normal.
.. admonition:: When to use a raw save
Generally speaking, you shouldn't need to use a raw save. Disabling field
pre-processing is an extraordinary measure that should only be required
in extraordinary circumstances, such as setting up reliable test
conditions.
Saving changes to objects
=========================
@@ -211,11 +180,11 @@ Saving ForeignKey and ManyToManyField fields
--------------------------------------------
Updating ``ForeignKey`` fields works exactly the same way as saving a normal
field; simply assign an object of the right type to the field in question::
field; simply assign an object of the right type to the field in question::
cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog
entry.save()
cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog
entry.save()
Updating a ``ManyToManyField`` works a little differently; use the ``add()``
method on the field to add a record to the relation::
@@ -422,6 +391,14 @@ This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``)::
Entry.objects.all()[5:10]
You can also slice from the item ''N'' to the end of the queryset. For
example, to return everything from the fixth item onwards::
Entry.objects.all()[5:]
How this last example is implemented in SQL varies depending upon the database
used, but it is supported in all cases.
Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't
evaluate the query. An exception is if you use the "step" parameter of Python
slice syntax. For example, this would actually execute the query in order to
@@ -514,15 +491,70 @@ like so::
Note: ``order_by('?')`` queries may be expensive and slow, depending on the
database backend you're using.
To order by a field in a different table, add the other table's name and a dot,
like so::
To order by a field in a different model, use the same syntax as when you are
querying across model relations. That is, the name of the field, followed by a
double underscore (``__``), followed by the name of the field in the new model,
and so on for as many models as you want to join. For example::
Entry.objects.order_by('blogs_blog.name', 'headline')
Entry.objects.order_by('blog__name', 'headline')
If you try to order by a field that is a relation to another model, Django will
use the default ordering on the related model (or order by the related model's
primary key if there is no ``Meta.ordering`` specified. For example::
Entry.objects.order_by('blog')
...is identical to::
Entry.objects.order_by('blog__id')
...since the ``Blog`` model has no default ordering specified.
Be cautious when ordering by fields in related models if you are also using
``distinct()``. See the note in the `distinct()`_ section for an explanation
of how related model ordering can change the expected results.
It is permissible to specify a multi-valued field to order the results by (for
example, a ``ManyToMany`` field). Normally this won't be a sensible thing to
do and it's really an advanced usage feature. However, if you know that your
queryset's filtering or available data implies that there will only be one
ordering piece of data for each of the main items you are selecting, the
ordering may well be exactly what you want to do. Use ordering on multi-valued
fields with care and make sure the results are what you expect.
**New in Django development version:** If you don't want any ordering to be
applied to a query, not even the default ordering, call ``order_by()`` with no
parameters.
**New in Django development version:** The syntax for ordering across related
models has changed. See the `Django 0.96 documentation`_ for the old behaviour.
.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield
There's no way to specify whether ordering should be case sensitive. With
respect to case-sensitivity, Django will order results however your database
backend normally orders them.
``reverse()``
~~~~~~~~~~~~~
**New in Django development version**
If you want to reverse the order in which a queryset's elements are returned,
you can use the ``reverse()`` method. Calling ``reverse()`` a second time
restores the ordering back to the normal direction.
To retrieve the ''last'' five items in a queryset, you could do this::
my_queryset.reverse()[:5]
Note that this is not quite the same as slicing from the end of a sequence in
Python. The above example will return the last item first, then the
penultimate item and so on. If we had a Python sequence and looked at
``seq[:-5]``, we would see the fifth-last item first. Django doesn't support
that mode of access (slicing from the end), since it is not possible to do it
efficiently in SQL.
``distinct()``
~~~~~~~~~~~~~~
@@ -531,10 +563,28 @@ eliminates duplicate rows from the query results.
By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this
is rarely a problem, because simple queries such as ``Blog.objects.all()``
don't introduce the possibility of duplicate result rows.
don't introduce the possibility of duplicate result rows. However, if your
query spans multiple tables, it's possible to get duplicate results when a
``QuerySet`` is evaluated. That's when you'd use ``distinct()``.
However, if your query spans multiple tables, it's possible to get duplicate
results when a ``QuerySet`` is evaluated. That's when you'd use ``distinct()``.
.. note::
Any fields used in an ``order_by()`` call are included in the SQL
``SELECT`` columns. This can sometimes lead to unexpected results when
used in conjuntion with ``distinct()``. If you order by fields from a
related model, those fields will be added to the selected columns and they
may make otherwise duplicate rows appear to be distinct. Since the extra
columns don't appear in the returned results (they are only there to
support ordering), it sometimes looks like non-distinct results are being
returned.
Similarly, if you use a ``values()`` query to restrict the columns
selected, the columns used in any ``order_by()`` (or default model
ordering) will still be involved and may affect uniqueness of the results.
The moral here is that if you are using ``distinct()`` be careful about
ordering by related models. Similarly, when using ``distinct()`` and
``values()`` together, be careful when ordering by fields not in the
``values()`` call.
``values(*fields)``
~~~~~~~~~~~~~~~~~~~
@@ -569,6 +619,43 @@ Example::
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]
You can also retrieve values from across ``ForeignKey`` relations by using
double underscores to separate the field names, just as when calling the
``filter()`` command. For example::
>>> Entry.objects.values('blog__name').distinct()
[{'name': 'Beatles Blog'}]
A couple of subtleties that are worth mentioning:
* The ``values()`` method does not return anything for ``ManyToManyField``
attributes and will raise an error if you try to pass in this type of
field to it.
* If you have a field called ``foo`` that is a ``ForeignKey``, the default
``values()`` call will return a dictionary key called ``foo_id``, since
this is the name of the hidden model attribute that stores the actual
value (the ``foo`` attribute refers to the related model). When you are
calling ``values()`` and passing in field names, you can pass in either
``foo`` or ``foo_id`` and you will get back the same thing (the
dictionary key will match the field name you passed in).
For example::
>>> Entry.objects.values()
[{'blog_id: 1, 'headline': u'First Entry', ...}, ...]
>>> Entry.objects.values('blog')
[{'blog': 1}, ...]
>>> Entry.objects.values('blog_id')
[{'blog_id': 1}, ...]
* When using ``values()`` together with ``distinct()``, be aware that
ordering can affect the results. See the note in the `distinct()`_
section, above, for details.
**New in Django development version:** Previously, it was not possible to pass
``blog_id`` to ``values()`` in the above example, only ``blog``.
A ``ValuesQuerySet`` is useful when you know you're only going to need values
from a small number of the available fields and you won't need the
functionality of a model instance object. It's more efficient to select only
@@ -586,6 +673,34 @@ followed (optionally) by any output-affecting methods (such as ``values()``),
but it doesn't really matter. This is your chance to really flaunt your
individualism.
``values_list(*fields)``
~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
This is similar to ``values()`` except that instead of returning a list of
dictionaries, it returns a list of tuples. Each tuple contains the value from
the respective field passed into the ``values_list()`` call -- so the first
item is the first field, etc. For example::
>>> Entry.objects.values_list('id', 'headling')
[(1, u'First entry'), ...]
If you only pass in a single field, you can also pass in the ``flat``
parameter. If ``True``, this will mean the returned results are single values,
rather than one-tuples. An example should make the difference clearer::
>>> Entry.objects.values_list('id').order_by('id')
[(1,), (2,), (3,), ...]
>>> Entry.objects.values_list('id', flat=True).order_by('id')
[1, 2, 3, ...]
It is an error to pass in ``flat`` when there is more than one field.
If you don't pass any values to ``values_list()``, it will return all the
fields in the model, in the order they were declared.
``dates(field, kind, order='ASC')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -635,6 +750,17 @@ Examples::
>>> Entry.objects.none()
[]
``all()``
~~~~~~~~~~
**New in Django development version**
Returns a ''copy'' of the current ``QuerySet`` (or ``QuerySet`` subclass you
pass in). This can be useful in some situations where you might want to pass
in either a model manager or a ``QuerySet`` and do further filtering on the
result. You can safely call ``all()`` on either object and then you'll
definitely have a ``QuerySet`` to work with.
``select_related()``
~~~~~~~~~~~~~~~~~~~~
@@ -687,8 +813,8 @@ related ``Person`` *and* the related ``City``::
p = b.author # Hits the database.
c = p.hometown # Hits the database.
Note that ``select_related()`` does not follow foreign keys that have
``null=True``.
Note that, by default, ``select_related()`` does not follow foreign keys that
have ``null=True``.
Usually, using ``select_related()`` can vastly improve performance because your
app can avoid many database calls. However, in situations with deeply nested
@@ -705,8 +831,43 @@ follow::
The ``depth`` argument is new in the Django development version.
``extra(select=None, where=None, params=None, tables=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version:** Sometimes you only need to access
specific models that are related to your root model, not all of the related
models. In these cases, you can pass the related field names to
``select_related()`` and it will only follow those relations. You can even do
this for models that are more than one relation away by separating the field
names with double underscores, just as for filters. For example, if we have
thise model::
class Room(models.Model):
# ...
building = models.ForeignKey(...)
class Group(models.Model):
# ...
teacher = models.ForeignKey(...)
room = models.ForeignKey(Room)
subject = models.ForeignKey(...)
...and we only needed to work with the ``room`` and ``subject`` attributes, we
could write this::
g = Group.objects.select_related('room', 'subject')
This is also valid::
g = Group.objects.select_related('room__building', 'subject')
...and would also pull in the ``building`` relation.
You can only refer to ``ForeignKey`` relations in the list of fields passed to
``select_related``. You *can* refer to foreign keys that have ``null=True``
(unlike the default ``select_related()`` call). It's an error to use both a
list of fields and the ``depth`` parameter in the same ``select_related()``
call, since they are conflicting options.
``extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes, the Django query syntax by itself can't easily express a complex
``WHERE`` clause. For these edge cases, Django provides the ``extra()``
@@ -763,6 +924,21 @@ of the arguments is required, but you should use at least one of them.
some database backends, such as some MySQL versions, don't support
subqueries.
**New in Django development version**
In some rare cases, you might wish to pass parameters to the SQL fragments
in ``extra(select=...)```. For this purpose, use the ``select_params``
parameter. Since ``select_params`` is a sequence and the ``select``
attribute is a dictionary, some care is required so that the parameters
are matched up correctly with the extra select pieces. In this situation,
you should use a ``django.utils.datastructures.SortedDict`` for the
``select`` value, not just a normal Python dictionary.
This will work, for example::
Blog.objects.extra(
select=SortedDict(('a', '%s'), ('b', '%s')),
select_params=('one', 'two'))
``where`` / ``tables``
You can define explicit SQL ``WHERE`` clauses -- perhaps to perform
non-explicit joins -- by using ``where``. You can manually add tables to
@@ -779,20 +955,61 @@ of the arguments is required, but you should use at least one of them.
SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
Be careful when using the ``tables`` parameter if you're specifying
tables that are already used in the query. When you add extra tables
via the ``tables`` parameter, Django assumes you want that table included
an extra time, if it is already included. That creates a problem,
since the table name will then be given an alias. If a table appears
multiple times in an SQL statement, the second and subsequent occurrences
must use aliases so the database can tell them apart. If you're
referring to the extra table you added in the extra ``where`` parameter
this is going to cause errors.
Normally you'll only be adding extra tables that don't already appear in
the query. However, if the case outlined above does occur, there are a few
solutions. First, see if you can get by without including the extra table
and use the one already in the query. If that isn't possible, put your
``extra()`` call at the front of the queryset construction so that your
table is the first use of that table. Finally, if all else fails, look at
the query produced and rewrite your ``where`` addition to use the alias
given to your extra table. The alias will be the same each time you
construct the queryset in the same way, so you can rely upon the alias
name to not change.
``order_by``
If you need to order the resulting queryset using some of the new fields
or tables you have included via ``extra()`` use the ``order_by`` parameter
to ``extra()`` and pass in a sequence of strings. These strings should
either be model fields (as in the normal ``order_by()`` method on
querysets), of the form ``table_name.column_name`` or an alias for a column
that you specified in the ``select`` parameter to ``extra()``.
For example::
q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
q = q.extra(order_by = ['-is_recent'])
This would sort all the items for which ``is_recent`` is true to the front
of the result set (``True`` sorts before ``False`` in a descending
ordering).
This shows, by the way, that you can make multiple calls to
``extra()`` and it will behave as you expect (adding new constraints each
time).
``params``
The ``select`` and ``where`` parameters described above may use standard
Python database string placeholders -- ``'%s'`` to indicate parameters the
database engine should automatically quote. The ``params`` argument is a
list of any extra parameters to be substituted.
The ``where`` parameter described above may use standard Python database
string placeholders -- ``'%s'`` to indicate parameters the database engine
should automatically quote. The ``params`` argument is a list of any extra
parameters to be substituted.
Example::
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Always use ``params`` instead of embedding values directly into ``select``
or ``where`` because ``params`` will ensure values are quoted correctly
according to your particular backend. (For example, quotes will be escaped
correctly.)
Always use ``params`` instead of embedding values directly into ``where``
because ``params`` will ensure values are quoted correctly according to
your particular backend. (For example, quotes will be escaped correctly.)
Bad::
@@ -802,8 +1019,9 @@ of the arguments is required, but you should use at least one of them.
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
The combined number of placeholders in the list of strings for ``select``
or ``where`` should equal the number of values in the ``params`` list.
**New in Django development version** The ``select_params`` argument to
``extra()`` is new. Previously, you could attempt to pass parameters for
``select`` in the ``params`` argument, but it worked very unreliably.
QuerySet methods that do not return QuerySets
---------------------------------------------
@@ -1031,7 +1249,12 @@ Examples::
SQL equivalents::
SELECT ... WHERE id = 14;
SELECT ... WHERE id = NULL;
SELECT ... WHERE id IS NULL;
**New in Django development version:** The semantics of ``id__exact=None`` have
changed in the development version. Previously, it was (intentionally)
converted to ``WHERE id = NULL`` at the SQL level, which would never match
anything. It has now been changed to behave the same as ``id__isnull=True``.
iexact
~~~~~~
@@ -1261,14 +1484,6 @@ SQL equivalent::
SELECT ... WHERE pub_date IS NULL;
.. admonition:: ``__isnull=True`` vs ``__exact=None``
There is an important difference between ``__isnull=True`` and
``__exact=None``. ``__exact=None`` will *always* return an empty result
set, because SQL requires that no value is equal to ``NULL``.
``__isnull`` determines if the field is currently holding the value
of ``NULL`` without performing a comparison.
search
~~~~~~
@@ -1368,6 +1583,11 @@ equivalent::
Entry.objects.filter(blog__id=3) # __exact is implied
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact
.. note::
Because of this shortcut, you cannot have a field called ``pk`` that is not
the primary key of the model. It will always be replaced by the name of the
model's primary key in queries.
Lookups that span relationships
-------------------------------
@@ -1392,6 +1612,60 @@ whose ``headline`` contains ``'Lennon'``::
Blog.objects.filter(entry__headline__contains='Lennon')
Spanning multi-valued relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
When you are filtering an object based on a ``ManyToManyField`` or a reverse
``ForeignKeyField``, there are two different sorts of filter you may be
interested in. Consider the ``Blog``/``Entry`` relationship (``Blog`` to
``Entry`` is a one-to-many relation). We might be interested in finding blogs
that have an entry which has both *"Lennon"* in the headline and was published
today. Or we might want to find blogs that have an entry with *"Lennon"* in
the headline as well as an entry that was published today. Since there are
multiple entries associated with a single ``Blog``, both of these queries are
possible and make sense in some situations.
The same type of situation arises with a ``ManyToManyField``. For example, if
an ``Entry`` has a ``ManyToManyField`` called ``tags``, we might want to find
entries linked to tags called *"music"* and *"bands"* or we might want an
entry that contains a tag with a name of *"music"* and a status of *"public"*.
To handle both of these situations, Django has a consistent way of processing
``filter()`` and ``exclude()`` calls. Everything inside a single ``filter()``
call is applied simultaneously to filter out items matching all those
requirements. Successive ``filter()`` calls further restrict the set of
objects, but for multi-valued relations, they apply to any object linked to
the primary model, not necessarily those objects that were selected by an
earlier ``filter()`` call.
That may sound a bit confusing, so hopefully an example will clarify. To
select all blogs that contains entries with *"Lennon"* in the headline and
were published today, we would write::
Blog.objects.filter(entry__headline__contains='Lennon',
entry__pub_date=datetime.date.today())
To select all blogs that contain an entry with *"Lennon"* in the headline
**as well as** an entry that was published today, we would write::
Blog.objects.filter(entry__headline__contains='Lennon').filter(
entry__pub_date=datetime.date.today())
In this second example, the first filter restricted the queryset to all those
blogs linked to that particular type of entry. The second filter restricted
the set of blogs *further* to those that are also linked to the second type of
entry. The entries select by the second filter may or may not be the same as
the entries in the first filter. We are filtering the ``Blog`` items with each
filter statement, not the ``Entry`` items.
All of this behaviour also applies to ``exclude()``: all the conditions in a
single ``exclude()`` statement apply to a single instance (if those conditions
are talking about the same multi-valued relation). Conditions in subsequent
``filter()`` or ``exclude()`` calls that refer to the same relation may end up
filtering on different linked objects.
Escaping percent signs and underscores in LIKE statements
---------------------------------------------------------
@@ -1496,6 +1770,12 @@ This is equivalent to the following SQL ``WHERE`` clause::
You can compose statements of arbitrary complexity by combining ``Q`` objects
with the ``&`` and ``|`` operators. You can also use parenthetical grouping.
**New in Django development version:** ``Q`` objects can also be negated using
the ``~`` operator, allowing for combined lookups that combine both a normal
query and a negated (``NOT``) query::
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
Each lookup function that takes keyword-arguments (e.g. ``filter()``,
``exclude()``, ``get()``) can also be passed one or more ``Q`` objects as
positional (not-named) arguments. If you provide multiple ``Q`` object
@@ -1815,6 +2095,34 @@ complete query set::
Entry.objects.all().delete()
Updating multiple objects at once
=================================
**New in Django development version**
Sometimes you want to set a field to a particular value for all the objects in
a queryset. You can do this with the ``update()`` method. For example::
# Update all the headlings to the same value.
Entry.objects.all().update(headline='Everything is the same')
You can only set non-relation fields and ``ForeignKey`` fields using this
method and the value you set the field to must be a normal Python value (you
can't set a field to be equal to some other field at the moment).
To update ``ForeignKey`` fields, set the new value to be the new model
instance you want to point to. Example::
b = Blog.objects.get(pk=1)
# Make all entries belong to this blog.
Entry.objects.all().update(blog=b)
The ``update()`` method is applied instantly and doesn't return anything
(similar to ``delete()``). The only restriction on the queryset that is
updated is that it can only access one database table, the model's main
table. So don't try to filter based on related fields or anything like that;
it won't work.
Extra instance methods
======================

View 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 indvidually. 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 explicity 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
===================