Merged the queryset-refactor branch into trunk.

This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.

Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658


git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-04-27 02:50:16 +00:00
parent c91a30f00f
commit 9c52d56f6f
57 changed files with 5717 additions and 1739 deletions

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
===================