Proofread docs/db-api.txt

git-svn-id: http://code.djangoproject.com/svn/django/trunk@2820 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-05-03 06:22:08 +00:00
parent c62a014049
commit 227d48af1c
1 changed files with 250 additions and 174 deletions

View File

@ -1032,6 +1032,30 @@ equivalent::
Entry.objects.filter(blog__id__exact=3) Entry.objects.filter(blog__id__exact=3)
Entry.objects.filter(blog__pk=3) Entry.objects.filter(blog__pk=3)
Lookups that span relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Django offers a powerful and intuitive way to "follow" relationships in
lookups, taking care of the SQL ``JOIN``s for you automatically, behind the
scenes. To span a relationship, just use the field name of related fields
across models, separated by double underscores, until you get to the field you
want.
This example retrieves all ``Entry`` objects with a ``Blog`` whose ``name``
is ``'Beatles Blog'``::
Entry.objects.filter(blog__name__exact='Beatles Blog')
This spanning can be as deep as you'd like.
It works backwards, too. To refer to a "reverse" relationship, just use the
lowercase name of the model.
This example retrieves all ``Blog`` objects who have at least one ``Entry``
whose ``headline`` contains ``'Lennon'``::
Blog.objects.filter(entry__headline__contains='Lennon')
Escaping parenthesis and underscores in LIKE statements Escaping parenthesis and underscores in LIKE statements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1106,37 +1130,41 @@ primary key field is called ``name``, these two statements are equivalent::
some_obj == other_obj some_obj == other_obj
some_obj.name == other_obj.name some_obj.name == other_obj.name
OR lookups Complex lookups with Q objects
========== ==============================
Keyword argument queries are "AND"ed together. If you have more Keyword argument queries -- in ``filter()``, etc. -- are "AND"ed together. If
complex query requirements (for example, you need to include an ``OR`` you need to execute more more complex queries (for example, queries with ``OR``
statement in your query), you need to use ``Q`` objects. statements), you can use ``Q`` objects.
A ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a A ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a
collection of keyword arguments. These keyword arguments are specified in collection of keyword arguments. These keyword arguments are specified as in
the same way as keyword arguments to the basic lookup functions like get() "Field lookups" above.
and filter(). For example::
For example, this ``Q`` object encapsulates a single ``LIKE`` query::
Q(question__startswith='What') Q(question__startswith='What')
is a ``Q`` object encapsulating a single ``LIKE`` query. ``Q`` objects can be ``Q`` objects can be combined using the ``&`` and ``|`` operators. When an
combined using the ``&`` and ``|`` operators. When an operator is used on two operator is used on two ``Q`` objects, it yields a new ``Q`` object.
``Q`` objects, it yields a new ``Q`` object. For example the statement::
For example, this statement yields a single ``Q`` object that represents the
"OR" of two ``"question__startswith"`` queries::
Q(question__startswith='Who') | Q(question__startswith='What') Q(question__startswith='Who') | Q(question__startswith='What')
... yields a single ``Q`` object that represents the "OR" of two This is equivalent to the following SQL ``WHERE`` clause::
"question__startswith" queries, equivalent to the SQL WHERE clause::
... WHERE question LIKE 'Who%' OR question LIKE 'What%' WHERE question LIKE 'Who%' OR question LIKE 'What%'
You can compose statements of arbitrary complexity by combining ``Q`` objects You can compose statements of arbitrary complexity by combining ``Q`` objects
with the ``&`` and ``|`` operators. Parenthetical grouping can also be used. with the ``&`` and ``|`` operators. You can also use parenthetical grouping.
One or more ``Q`` objects can then provided as arguments to the lookup Each lookup function that takes keyword-arguments (e.g. ``filter()``,
functions. If multiple ``Q`` object arguments are provided to a lookup ``exclude()``, ``get()``) can also be passed one or more ``Q`` objects as
function, they will be "AND"ed together. For example:: positional (not-named) arguments. If you provide multiple ``Q`` object
arguments to a lookup function, the arguments will be "AND"ed together. For
example::
Poll.objects.get( Poll.objects.get(
Q(question__startswith='Who'), Q(question__startswith='Who'),
@ -1148,11 +1176,10 @@ function, they will be "AND"ed together. For example::
SELECT * from polls WHERE question LIKE 'Who%' SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
If necessary, lookup functions can mix the use of ``Q`` objects and keyword Lookup functions can mix the use of ``Q`` objects and keyword arguments. All
arguments. All arguments provided to a lookup function (be they keyword arguments provided to a lookup function (be they keyword arguments or ``Q``
argument or ``Q`` object) are "AND"ed together. However, if a ``Q`` object is objects) are "AND"ed together. However, if a ``Q`` object is provided, it must
provided, it must precede the definition of any keyword arguments. For precede the definition of any keyword arguments. For example::
example::
Poll.objects.get( Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
@ -1167,193 +1194,242 @@ example::
... would not be valid. ... would not be valid.
A ``Q`` objects can also be provided to the ``complex`` keyword argument. For example::
Poll.objects.get(
complex=Q(question__startswith='Who') &
(Q(pub_date=date(2005, 5, 2)) |
Q(pub_date=date(2005, 5, 6))
)
)
See the `OR lookups examples page`_ for more examples. See the `OR lookups examples page`_ for more examples.
.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/ .. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/
Related objects
===============
Relationships (joins) When you define a relationship in a model (i.e., a ``ForeignKey``,
===================== ``OneToOneField``, or ``ManyToManyField``), instances of that model will have
a convenient API to access the related object(s).
When you define a relationship in a model (i.e., a ForeignKey, Using the models at the top of this page, for example, an ``Entry`` object ``e``
OneToOneField, or ManyToManyField), Django uses the name of the can get its associated ``Blog`` object by accessing the ``blog`` attribute:
relationship to add a descriptor_ on every instance of the model. ``e.blog``.
This descriptor behaves just like a normal attribute, providing
access to the related object or objects. For example,
``mychoice.poll`` will return the poll object associated with a specific
instance of ``Choice``.
.. _descriptor: http://users.rcn.com/python/download/Descriptor.htm (Behind the scenes, this functionality is implemented by Python descriptors_.
This shouldn't really matter to you, but we point it out here for the curious.)
Django also adds a descriptor for the 'other' side of the relationship - Django also creates API accessors for the "other" side of the relationship --
the link from the related model to the model that defines the relationship. the link from the related model to the model that defines the relationship.
Since the related model has no explicit reference to the source model, For example, a ``Blog`` object ``b`` has access to a list of all related
Django will automatically derive a name for this descriptor. The name that ``Entry`` objects via the ``entry_set`` attribute: ``b.entry_set.all()``.
Django chooses depends on the type of relation that is represented. However,
if the definition of the relation has a `related_name` parameter, Django
will use this name in preference to deriving a name.
There are two types of descriptor that can be employed: Single Object All examples in this section use the sample ``Blog``, ``Author`` and ``Entry``
Descriptors and Object Set Descriptors. The following table describes models defined at the top of this page.
when each descriptor type is employed. The local model is the model on
which the relation is defined; the related model is the model referred
to by the relation.
=============== ============= ============= .. _descriptors: http://users.rcn.com/python/download/Descriptor.htm
Relation Type Local Model Related Model
=============== ============= =============
OneToOneField Single Object Single Object
ForeignKey Single Object Object Set One-to-many relationships
-------------------------
ManyToManyField Object Set Object Set Forward
=============== ============= ============= ~~~~~~~
Single object descriptor If a model has a ``ForeignKey``, instances of that model will have access to
------------------------ the related (foreign) object via a simple attribute of the model.
If the related object is a single object, the descriptor acts Example::
just as if the related object were an attribute::
# Obtain the existing poll e = Entry.objects.get(id=2)
old_poll = mychoice.poll e.blog # Returns the related Blog object.
# Set a new poll
mychoice.poll = new_poll
# Save the change
mychoice.save()
Whenever a change is made to a Single Object Descriptor, save() You can get and set via a foreign-key attribute. As you may expect, changes to
must be called to commit the change to the database. the foreign key aren't saved to the database until you call ``save()``.
Example::
If no `related_name` parameter is defined, Django will use the e = Entry.objects.get(id=2)
lower case version of the source model name as the name for the e.blog = some_blog
related descriptor. For example, if the ``Choice`` model had e.save()
a field::
coordinator = models.OneToOneField(User) If a ``ForeignKey`` field has ``null=True`` set (i.e., it allows ``NULL``
values), you can assign ``None`` to it. Example::
... instances of the model ``User`` would be able to call: e = Entry.objects.get(id=2)
e.blog = None
e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"
old_choice = myuser.choice Forward access to one-to-many relationships is cached the first time the
myuser.choice = new_choice related object is accessed. Subsequent accesses to the foreign key on the same
object instance are cached. Example::
By default, relations do not allow values of None; if you attempt e = Entry.objects.get(id=2)
to assign None to a Single Object Descriptor, an AttributeError print e.blog # Hits the database to retrieve the associated Blog.
will be thrown. However, if the relation has 'null=True' set print e.blog # Doesn't hit the database; uses cached version.
(i.e., the database will allow NULLs for the relation), None can
be assigned and returned by the descriptor to represent empty
relations.
Access to Single Object Descriptors is cached. The first time Note that the ``select_related()`` ``QuerySet`` method recursively prepopulates
a descriptor on an instance is accessed, the database will be the cache of all one-to-many relationships ahead of time. Example::
queried, and the result stored. Subsequent attempts to access
the descriptor on the same instance will use the cached value.
Object set descriptor e = Entry.objects.select_related().get(id=2)
--------------------- print e.blog # Doesn't hit the database; uses cached version.
print e.blog # Doesn't hit the database; uses cached version.
An Object Set Descriptor acts just like the Manager - as an initial Query ``select_related()`` is documented in the "QuerySet methods that return new
Set describing the set of objects related to an instance. As such, any QuerySets" section above.
query refining technique (filter, exclude, etc) can be used on the Object
Set descriptor. This also means that Object Set Descriptor cannot be evaluated
directly - the ``all()`` method must be used to produce a Query Set that
can be evaluated.
If no ``related_name`` parameter is defined, Django will use the lower case Backward
version of the source model name appended with `_set` as the name for the ~~~~~~~~
related descriptor. For example, every ``Poll`` object has a ``choice_set``
descriptor.
The Object Set Descriptor has utility methods to add objects to the If a model has a ``ForeignKey``, instances of the foreign-key model will have
related object set: access to a ``Manager`` that returns all instances of the first model. By
default, this ``Manager`` is named ``FOO_set``, where ``FOO`` is the source
model name, lowercased. This ``Manager`` returns ``QuerySets``, which can be
filtered and manipulated as described in the "Retrieving objects" section
above.
``add(obj1, obj2, ...)`` Example::
Add the specified objects to the related object set.
``create(\**kwargs)`` b = Blog.objects.get(id=1)
Create a new object, and put it in the related object set. See b.entry_set.all() # Returns all Entry objects related to Blog.
_`Creating new objects`
The Object Set Descriptor may also have utility methods to remove objects # b.entry_set is a Manager that returns QuerySets.
from the related object set: b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count()
``remove(obj1, obj2, ...)`` You can override the ``FOO_set`` name by setting the ``related_name``
Remove the specified objects from the related object set. parameter in the ``ForeignKey()`` definition. For example, if the ``Entry``
model was altered to ``blog = ForeignKey(Blog, related_name='entries')``, the
above example code would look like this::
``clear()`` b = Blog.objects.get(id=1)
Remove all objects from the related object set. b.entries.all() # Returns all Entry objects related to Blog.
These two removal methods will not exist on ForeignKeys where ``Null=False`` # b.entries is a Manager that returns QuerySets.
(such as in the Poll example). This is to prevent database inconsistency - if b.entries.filter(headline__contains='Lennon')
the related field cannot be set to None, then an object cannot be removed b.entries.count()
from one relation without adding it to another.
The members of a related object set can be assigned from any iterable object. You cannot access a reverse ``ForeignKey`` ``Manager`` from the class; it must
For example:: be accessed from an instance. Example::
mypoll.choice_set = [choice1, choice2] Blog.entry_set # Raises AttributeError: "Manager must be accessed via instance".
If the ``clear()`` method is available, any pre-existing objects will be removed In addition to the ``QuerySet`` methods defined in "Retrieving objects" above,
from the Object Set before all objects in the iterable (in this case, a list) the ``ForeignKey`` ``Manager`` has these additional methods:
are added to the choice set. If the ``clear()`` method is not available, all
objects in the iterable will be added without removing any existing elements.
Each of these operations on the Object Set Descriptor has immediate effect * ``add(obj1, obj2, ...)``: Adds the specified model objects to the related
on the database - every add, create and remove is immediately and object set.
Example::
b = Blog.objects.get(id=1)
e = Entry.objects.get(id=234)
b.entry_set.add(e) # Associates Entry e with Blog b.
* ``create(**kwargs)``: Creates a new object, saves it and puts it in the
related object set. Returns the newly created object.
Example::
b = Blog.objects.get(id=1)
e = b.entry_set.create(headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1))
# No need to call e.save() at this point -- it's already been saved.
This is equivalent to (but much simpler than)::
b = Blog.objects.get(id=1)
e = Entry(blog=b, headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1))
e.save()
Note that there's no need to specify the keyword argument of the model
that defines the relationship. In the above example, we don't pass the
parameter ``blog`` to ``create()``. Django figures out that the new
``Entry`` object's ``blog`` field should be set to ``b``.
* ``remove(obj1, obj2, ...)``: Removes the specified model objects from the
related object set.
Example::
b = Blog.objects.get(id=1)
e = Entry.objects.get(id=234)
b.entry_set.remove(e) # Disassociates Entry e from Blog b.
In order to prevent database inconsistency, this method only exists on
``ForeignKey``s where ``null=True``. If the related field can't be set to
``None`` (``NULL``), then an object can't be removed from a relation
without being added to another. In the above example, removing ``e`` from
``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because
the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this is invalid.
* ``clear()``: Removes all objects from the related object set.
Example::
b = Blog.objects.get(id=1)
b.entry_set.clear()
Note this doesn't delete the related objects -- it just disassociates
them.
Just like ``remove()``, ``clear()`` is only available on ``ForeignKey``s
where ``null=True``.
To assign the members of a related set in one fell swoop, just assign to it
from any iterable object. Example::
b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]
If the ``clear()`` method is available, any pre-existing objects will be
removed from the ``entry_set`` before all objects in the iterable (in this
case, a list) are added to the set. If the ``clear()`` method is *not*
available, all objects in the iterable will be added without removing any
existing elements.
Each "reverse" operation described in this section has an immediate effect on
the database. Every addition, creation and deletion is immediately and
automatically saved to the database. automatically saved to the database.
Relationships and queries Many-to-many relationships
========================= --------------------------
When composing a ``filter`` or ``exclude`` refinement, it may be necessary to Both ends of a many-to-many relationship get automatic API access to the other
include conditions that span relationships. Relations can be followed as deep end. The API works just as a "backward" one-to-many relationship. See _Backward
as required - just add descriptor names, separated by double underscores, to above.
describe the full path to the query attribute. The query::
Foo.objects.filter(name1__name2__name3__attribute__lookup=value) The only difference is in the attribute naming: The model that defines the
``ManyToManyField`` uses the attribute name of that field itself, whereas the
"reverse" model uses the lowercased model name of the original model, plus
``'_set'`` (just like reverse one-to-many relationships).
... is interpreted as 'get every Foo that has a name1 that has a name2 that An example makes this easier to understand::
has a name3 that has an attribute with lookup matching value'. In the Poll
example::
Choice.objects.filter(poll__slug__startswith="eggs") e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')
... describes the set of choices for which the related poll has a slug a = Author.objects.get(id=5)
attribute that starts with "eggs". Django automatically composes the joins a.entry_set.all() # Returns all Entry objects for this Author.
and conditions required for the SQL query.
Creating new related objects Like ``ForeignKey``, ``ManyToManyField`` can specify ``related_name``. In the
============================ above example, if the ``ManyToManyField`` in ``Entry`` had specified
``related_name='entries'``, then each ``Author`` instance would have an
``entries`` attribute instead of ``entry_set``.
Related objects are created using the ``create()`` convenience function on One-to-one relationships
the descriptor Manager for relation:: ------------------------
>>> p.choice_set.create(choice="Over easy", votes=0) The semantics of one-to-one relationships will be changing soon, so we don't
>>> p.choice_set.create(choice="Scrambled", votes=0) recommend you use them.
>>> p.choice_set.create(choice="Fertilized", votes=0)
>>> p.choice_set.create(choice="Poached", votes=0)
>>> p.choice_set.count()
4
Each of those ``create()`` methods is equivalent to (but much simpler than):: How are the backward relationships possible?
--------------------------------------------
>>> c = Choice(poll_id=p.id, choice="Over easy", votes=0) Other object-relational mappers require you to define relationships on both
>>> c.save() sides. The Django developers believe this is a violation of the DRY (Don't
Repeat Yourself) principle, so Django only requires you to define the
relationship on one end.
Note that when using the `create()`` method, you do not give any value But how is this possible, given that a model class doesn't know which other
for the ``id`` field, nor do you give a value for the field that stores model classes are related to it until those other model classes are loaded?
the relation (``poll_id`` in this case).
The ``create()`` method always returns the newly created object. The answer lies in the ``INSTALLED_APPS`` setting. The first time any model is
loaded, Django iterates over every model in ``INSTALLED_APPS`` and creates the
backward relationships in memory as needed. Essentially, one of the functions
of ``INSTALLED_APPS`` is to tell Django the entire model domain.
Deleting objects Deleting objects
================ ================
@ -1361,23 +1437,23 @@ Deleting objects
The delete method, conveniently, is named ``delete()``. This method immediately The delete method, conveniently, is named ``delete()``. This method immediately
deletes the object and has no return value. Example:: deletes the object and has no return value. Example::
>>> c.delete() e.delete()
Objects can also be deleted in bulk. Every Query Set has a ``delete()`` method You can also delete objects in bulk. Every ``QuerySet`` has a ``delete()``
that will delete all members of the query set. For example:: method, which deletes all members of that ``QuerySet``.
>>> Polls.objects.filter(pub_date__year=2005).delete() For example, this deletes all ``Entry`` objects with a ``pub_date`` year of
2005::
would bulk delete all Polls with a year of 2005. Note that ``delete()`` is the Entry.objects.filter(pub_date__year=2005).delete()
only Query Set method that is not exposed on the Manager itself.
This is a safety mechanism to prevent you from accidentally requesting Note that ``delete()`` is the only ``QuerySet`` method that is not exposed on a
``Polls.objects.delete()``, and deleting *all* the polls. ``Manager`` itself. This is a safety mechanism to prevent you from accidentally
requesting ``Entry.objects.delete()``, and deleting *all* the entries. If you
*do* want to delete all the objects, then you have to explicitly request a
complete query set::
If you *actually* want to delete all the objects, then you have to explicitly Entry.objects.all().delete()
request a complete query set::
Polls.objects.all().delete()
Extra instance methods Extra instance methods
====================== ======================
@ -1397,9 +1473,9 @@ following model::
('M', 'Male'), ('M', 'Male'),
('F', 'Female'), ('F', 'Female'),
) )
class Person class Person(models.Model):
name = meta.CharField(maxlength=20) name = models.CharField(maxlength=20)
gender = meta.CharField(maxlength=1, choices=GENDER_CHOICES) gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
...each ``Person`` instance will have a ``get_gender_display()`` method. Example:: ...each ``Person`` instance will have a ``get_gender_display()`` method. Example::