1
0
mirror of https://github.com/django/django.git synced 2025-07-05 02:09:13 +00:00

magic-removal: Continued rewrite of docs/db-api.txt. Still not finished.

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2749 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-04-27 05:14:03 +00:00
parent 1529aef3ff
commit 57607c8226

View File

@ -8,7 +8,8 @@ objects. This document explains that API.
.. _`data models`: http://www.djangoproject.com/documentation/model_api/ .. _`data models`: http://www.djangoproject.com/documentation/model_api/
Throughout this reference, we'll refer to the following Blog application:: Throughout this reference, we'll refer to the following models, which comprise
a weblog application::
class Blog(models.Model): class Blog(models.Model):
name = models.CharField(maxlength=100) name = models.CharField(maxlength=100)
@ -37,11 +38,20 @@ Throughout this reference, we'll refer to the following Blog application::
Creating objects Creating objects
================ ================
To represent database-table data in Python objects, Django uses an intuitive
system: A model class represents a database table, and an instance of that
class represents a particular record in the database table.
To create an object, instantiate it using keyword arguments to the model class, To create an object, instantiate it using keyword arguments to the model class,
then call ``save()`` to save it to the database. then call ``save()`` to save it to the database.
Example:: You import the model class from wherever it lives on the Python path, as you
may expect. (We point this out here because previous Django versions required
funky model importing.)
Assuming models live in a file ``mysite/blog/models.py``, here's an example::
from mysite.blog.models import Blog
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save() b.save()
@ -98,7 +108,8 @@ the previous record in the database::
b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.') b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save() # Overrides the previous blog with ID=3! b4.save() # Overrides the previous blog with ID=3!
See also "How Django knows to UPDATE vs. INSERT", below. See _`How Django knows to UPDATE vs. INSERT`, below, for the reason this
happens.
Explicitly specifying auto-primary-key values is mostly useful for bulk-saving Explicitly specifying auto-primary-key values is mostly useful for bulk-saving
objects, when you're confident you won't have primary-key collision. objects, when you're confident you won't have primary-key collision.
@ -127,7 +138,8 @@ for creating and changing objects. Django abstracts the need to use ``INSERT``
or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django
follows this algorithm: follows this algorithm:
* If the object's primary key attribute is set, Django executes a * If the object's primary key attribute is set to a value that evaluates to
``False`` (such as ``None`` or the empty string), Django executes a
``SELECT`` query to determine whether a record with the given primary key ``SELECT`` query to determine whether a record with the given primary key
already exists. already exists.
* If the record with the given primary key does already exist, Django * If the record with the given primary key does already exist, Django
@ -144,14 +156,12 @@ Retrieving objects
================== ==================
To retrieve objects from your database, you construct a ``QuerySet`` via a To retrieve objects from your database, you construct a ``QuerySet`` via a
``Manager``. ``Manager`` on your model class.
A ``QuerySet`` represents a collection of objects from your database. It can A ``QuerySet`` represents a collection of objects from your database. It can
have zero, one or many *filters* -- criteria that narrow down the collection have zero, one or many *filters* -- criteria that narrow down the collection
based on given parameters. based on given parameters. In SQL terms, a ``QuerySet`` equates to a ``SELECT``
statement, and a filter is a limiting clause such as ``WHERE`` or ``LIMIT``.
In SQL terms, a ``QuerySet`` equates to a ``SELECT`` statement, and a filter is
a limiting clause such as ``WHERE`` or ``LIMIT``.
You get a ``QuerySet`` by using your model's ``Manager``. Each model has at You get a ``QuerySet`` by using your model's ``Manager``. Each model has at
least one ``Manager``, and it's called ``objects`` by default. Access it least one ``Manager``, and it's called ``objects`` by default. Access it
@ -206,7 +216,7 @@ conditions. The two most common ways to refine a ``QuerySet`` are:
lookup parameters. lookup parameters.
The lookup parameters (``**kwargs`` in the above function definitions) should The lookup parameters (``**kwargs`` in the above function definitions) should
be in the format described in "Field lookups" below. be in the format described in _`Field lookups` below.
For example, to get a ``QuerySet`` of blog entries from the year 2006, use For example, to get a ``QuerySet`` of blog entries from the year 2006, use
``filter()`` like so:: ``filter()`` like so::
@ -220,7 +230,7 @@ from the root ``QuerySet``.)
Chaining filters Chaining filters
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
The result of refining a ``QuerySet`` is itself a ``Query Set``, so it's The result of refining a ``QuerySet`` is itself a ``QuerySet``, so it's
possible to chain refinements together. For example:: possible to chain refinements together. For example::
Entry.objects.filter( Entry.objects.filter(
@ -283,7 +293,7 @@ You can evaluate a ``QuerySet`` in the following ways:
* **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it. * **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it.
This is for convenience in the Python interactive interpreter, so you can This is for convenience in the Python interactive interpreter, so you can
immediately see your results. immediately see your results when using the API interactively.
* **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it. * **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it.
This, as you might expect, returns the length of the result list. This, as you might expect, returns the length of the result list.
@ -304,8 +314,8 @@ You can evaluate a ``QuerySet`` in the following ways:
iterating over a ``QuerySet`` will take advantage of your database to iterating over a ``QuerySet`` will take advantage of your database to
load data and instantiate objects only as you need them. load data and instantiate objects only as you need them.
Full list of QuerySet methods QuerySet methods that return new QuerySets
----------------------------- ------------------------------------------
Django provides a range of ``QuerySet`` refinement methods that modify either Django provides a range of ``QuerySet`` refinement methods that modify either
the types of results returned by the ``QuerySet`` or the way its SQL query is the types of results returned by the ``QuerySet`` or the way its SQL query is
@ -318,7 +328,7 @@ Returns a new ``QuerySet`` containing objects that match the given lookup
parameters. parameters.
The lookup parameters (``**kwargs``) should be in the format described in The lookup parameters (``**kwargs``) should be in the format described in
"Field lookups" below. Multiple parameters are joined via ``AND`` in the _`Field lookups` below. Multiple parameters are joined via ``AND`` in the
underlying SQL statement. underlying SQL statement.
exclude(**kwargs) exclude(**kwargs)
@ -328,18 +338,29 @@ Returns a new ``QuerySet`` containing objects that do *not* match the given
lookup parameters. lookup parameters.
The lookup parameters (``**kwargs``) should be in the format described in The lookup parameters (``**kwargs``) should be in the format described in
"Field lookups" below. Multiple parameters are joined via ``AND`` in the _`Field lookups` below. Multiple parameters are joined via ``AND`` in the
underlying SQL statement, and the whole thing is enclosed in a ``NOT()``. underlying SQL statement, and the whole thing is enclosed in a ``NOT()``.
This example excludes all entries whose ``pub_date`` is the current date/time This example excludes all entries whose ``pub_date`` is the current date/time
AND whose ``headline`` is "Hello":: AND whose ``headline`` is "Hello"::
Entry.objects.exclude(pub_date__gt=datetime.now(), headline='Hello') Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
In SQL terms, that evaluates to::
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
This example excludes all entries whose ``pub_date`` is the current date/time This example excludes all entries whose ``pub_date`` is the current date/time
OR whose ``headline`` is "Hello":: OR whose ``headline`` is "Hello"::
Entry.objects.exclude(pub_date__gt=datetime.now()).exclude(headline='Hello') Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
In SQL terms, that evaluates to::
SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'
Note the second example is more restrictive. Note the second example is more restrictive.
@ -370,8 +391,21 @@ There's no way to specify whether ordering should be case sensitive. With
respect to case-sensitivity, Django will order results however your database respect to case-sensitivity, Django will order results however your database
backend normally orders them. backend normally orders them.
distinct()
~~~~~~~~~~
Returns a new ``QuerySet`` that uses ``SELECT DISTINCT`` in its SQL query. This
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.
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()``.
values(*fields) values(*fields)
--------------- ~~~~~~~~~~~~~~~
Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of
dictionaries instead of model-instance objects. dictionaries instead of model-instance objects.
@ -420,29 +454,12 @@ followed (optionally) by any output-affecting methods (such as ``values()``),
but it doesn't really matter. This is your chance to really flaunt your but it doesn't really matter. This is your chance to really flaunt your
individualism. individualism.
distinct() dates(field, kind, order='ASC')
~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``distinct()`` method returns a new ``QuerySet`` that uses Returns a ``DateQuerySet`` -- a ``QuerySet`` that evaluates to a list of
``SELECT DISTINCT`` in its SQL query. This eliminates duplicate rows from the ``datetime.datetime`` objects representing all available dates of a particular
query results. kind within the contents of the ``QuerySet``.
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.
However, if your query spans multiple tables, or you're using a
``ValuesQuerySet`` with a ``fields`` clause, it's possible to get duplicate
results when a ``QuerySet`` is evaluated. That's when you'd use ``distinct()``.
TODO: Left off here
``dates(field, kind, order='ASC')``
-----------------------------------
Returns a Date Query Set - a Query Set that evaluates to a list of
``datetime.datetime`` objects representing all available dates of a
particular kind within the contents of the Query Set.
``field`` should be the name of a ``DateField`` or ``DateTimeField`` of your ``field`` should be the name of a ``DateField`` or ``DateTimeField`` of your
model. model.
@ -455,213 +472,504 @@ model.
* ``"month"`` returns a list of all distinct year/month values for the field. * ``"month"`` returns a list of all distinct year/month values for the field.
* ``"day"`` returns a list of all distinct year/month/day values for the field. * ``"day"`` returns a list of all distinct year/month/day values for the field.
``order``, which defaults to ``'ASC'``, should be either ``"ASC"`` or ``"DESC"``. ``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or
This specifies how to order the results. ``'DESC'``. This specifies how to order the results.
For example:: Examples::
>>> Poll.objects.dates('pub_date', 'year') >>> Entry.objects.dates('pub_date', 'year')
[datetime.datetime(2005, 1, 1)] [datetime.datetime(2005, 1, 1)]
>>> Poll.objects.dates('pub_date', 'month') >>> Entry.objects.dates('pub_date', 'month')
[datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)] [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)]
>>> Poll.objects.dates('pub_date', 'day') >>> Entry.objects.dates('pub_date', 'day')
[datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)] [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)]
>>> Poll.objects.dates('pub_date', 'day', order='DESC') >>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)] [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)]
>>> Poll.objects.filter(question__contains='name').dates('pub_date', 'day') >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.datetime(2005, 3, 20)] [datetime.datetime(2005, 3, 20)]
``select_related()`` select_related()
-------------------- ~~~~~~~~~~~~~~~~
Relations are the bread and butter of databases, so there's an option to "follow" Returns a ``QuerySet`` that will automatically "follow" foreign-key
all relationships and pre-fill them in a simple cache so that later calls to relationships, selecting that additional related-object data when it executes
objects with a one-to-many relationship don't have to hit the database. Do this by its query. This is a performance booster which results in (sometimes much)
passing ``select_related=True`` to a lookup. This results in (sometimes much) larger larger queries but means later use of foreign-key relationships won't require
queries, but it means that later use of relationships is much faster. database queries.
For example, using the Poll and Choice models from above, if you do the following:: The following examples illustrate the difference between plain lookups and
``select_related()`` lookups. Here's standard lookup::
c = Choice.objects.select_related().get(id=5) # Hits the database.
e = Entry.objects.get(id=5)
Then subsequent calls to ``c.poll`` won't hit the database. # Hits the database again to get the related Blog object.
b = e.blog
Note that ``select_related`` follows foreign keys as far as possible. If you have the And here's ``select_related`` lookup::
# Hits the database.
e = Entry.objects.select_related().get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
``select_related()`` follows foreign keys as far as possible. If you have the
following models:: following models::
class Poll(models.Model): class City(models.Model):
# ... # ...
class Choice(models.Model): class Person(models.Model):
# ... # ...
poll = models.ForeignKey(Poll) hometown = models.ForeignKey(City)
class SingleVote(meta.Model): class Book(meta.Model):
# ... # ...
choice = models.ForeignKey(Choice) author = models.ForeignKey(Person)
then a call to ``SingleVotes.objects.select_related().get(id=4)`` will ...then a call to ``Book.objects.select_related().get(id=4)`` will cache the
cache the related choice *and* the related poll:: related ``Person`` *and* the related ``City``::
>>> sv = SingleVotes.objects.select_related().get(id=4) b = Book.objects.select_related().get(id=4)
>>> c = sv.choice # Doesn't hit the database. p = b.author # Doesn't hit the database.
>>> p = c.poll # Doesn't hit the database. c = p.hometown # Doesn't hit the database.
>>> sv = SingleVotes.objects.get(id=4) sv = Book.objects.get(id=4) # No select_related() in this example.
>>> c = sv.choice # Hits the database. p = b.author # Hits the database.
>>> p = c.poll # Hits the database. c = p.hometown # Hits the database.
extra(select=None, where=None, params=None, tables=None)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``extra(params, select, where, tables)`` Sometimes, the Django query syntax by itself can't easily express a complex
---------------------------------------- ``WHERE`` clause. For these edge cases, Django provides the ``extra()``
``QuerySet`` modifier -- a hook for injecting specific clauses into the SQL
generated by a ``QuerySet``.
Sometimes, the Django query syntax by itself isn't quite enough. To cater for these By definition, these extra lookups may not be portable to different database
edge cases, Django provides the ``extra()`` Query Set modifier - a mechanism engines (because you're explicitly writing SQL code) and violate the DRY
for injecting specific clauses into the SQL generated by a Query Set. principle, so you should avoid them if possible.
Note that by definition these extra lookups may not be portable to different Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None
database engines (because you're explicitly writing SQL code) and should be of the arguments is required, but you should use at least one of them.
avoided if possible.:
``params``
All the extra-SQL params described below may use standard Python string
formatting codes to indicate parameters that the database engine will
automatically quote. The ``params`` argument can contain any extra
parameters to be substituted.
``select`` ``select``
The ``select`` keyword allows you to select extra fields. This should be a The ``select`` argument lets you put extra fields in the ``SELECT`` clause.
dictionary mapping attribute names to a SQL clause to use to calculate that It should be a dictionary mapping attribute names to SQL clauses to use to
attribute. For example:: calculate that attribute.
Poll.objects.extra( Example::
Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
As a result, each ``Entry`` object will have an extra attribute,
``is_recent``, a boolean representing whether the entry's ``pub_date`` is
greater than Jan. 1, 2006.
Django inserts the given SQL snippet directly into the ``SELECT``
statement, so the resulting SQL of the above example would be::
SELECT blog_entry.*, (pub_date > '2006-01-01')
FROM blog_entry;
The next example is more advanced; it does a subquery to give each
resulting ``Blog`` object an ``entry_count`` attribute, an integer count
of associated ``Entry`` objects.
Blog.objects.extra(
select={ select={
'choice_count': 'SELECT COUNT(*) FROM choices WHERE poll_id = polls.id' 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id'
} },
) )
Each of the resulting ``Poll`` objects will have an extra attribute, ``choice_count``, (In this particular case, we're exploiting the fact that the query will
an integer count of associated ``Choice`` objects. Note that the parenthesis required by already contain the ``blog_blog`` table in its ``FROM`` clause.)
most database engines around sub-selects are not required in Django's ``select``
clauses. The resulting SQL of the above example would be::
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id)
FROM blog_blog;
Note that the parenthesis required by most database engines around
subqueries are not required in Django's ``select`` clauses. Also note that
some database backends, such as some MySQL versions, don't support
subqueries.
``where`` / ``tables`` ``where`` / ``tables``
If you need to explicitly pass extra ``WHERE`` clauses -- perhaps to perform You can define explicit SQL ``WHERE`` clauses -- perhaps to perform
non-explicit joins -- use the ``where`` keyword. If you need to non-explicit joins -- by using ``where``. You can manually add tables to
join other tables into your query, you can pass their names to ``tables``. the SQL ``FROM`` clause by using ``tables``.
``where`` and ``tables`` both take a list of strings. All ``where`` parameters ``where`` and ``tables`` both take a list of strings. All ``where``
are "AND"ed to any other search criteria. parameters are "AND"ed to any other search criteria.
For example:: Example::
Poll.objects.filter( Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
question__startswith='Who').extra(where=['id IN (3, 4, 5, 20)'])
...translates (roughly) into the following SQL:: ...translates (roughly) into the following SQL::
SELECT * FROM polls_polls WHERE question LIKE 'Who%' AND id IN (3, 4, 5, 20); SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
``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.
Example::
Caching and QuerySets Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
---------------------
Each ``QuerySet`` contains a cache, to minimize database access. 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.)
In a newly created ``QuerySet``, this cache is empty. The first time a Bad::
``QuerySet`` is evaluated -- and, hence, a database query happens -- Django
saves the query results in the ``QuerySet``'s cache and returns the results
that have been explicitly requested (e.g., the next element, if the
``QuerySet`` is being iterated over). Subsequent evaluations of the
``QuerySet`` reuse the cached results.
Keep this caching behavior in mind, because it may bite you if you don't use Entry.objects.extra(where=["headline='Lennon'"])
your ``QuerySet``s correctly. For example, the following will create two
``QuerySet``s, evaluate them, and throw them away::
print [e.headline for e in Entry.objects.all()] Good::
print [e.pub_date for e in Entry.objects.all()]
That means the same database query will be executed twice, effectively doubling Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
your database load. Also, there's a possibility the two lists may not include
the same database records, because an ``Entry`` may have been added or deleted
in the split second between the two requests.
To avoid this problem, simply save the ``QuerySet`` and reuse it:: QuerySet methods that do not return QuerySets
---------------------------------------------
queryset = Poll.objects.all() The following ``QuerySet`` methods evaluate the ``QuerySet`` and return
print [p.headline for p in queryset] # Evaluate the query set. something *other than* a ``QuerySet``.
print [p.pub_date for p in queryset] # Re-use the cache from the evaluation.
These methods do not use a cache (see _`Caching and QuerySets` below). Rather,
they query the database each time they're called.
get(**kwargs)
~~~~~~~~~~~~~
Deleting objects Returns the object matching the given lookup parameters, which should be in
================ the format described in _`Field lookups`.
``get()`` raises ``AssertionError`` if more than one object was found.
``get()`` raises a ``DoesNotExist`` exception if an object wasn't found for the
given parameters. The ``DoesNotExist`` exception is an attribute of the model
class. Example::
Entry.objects.get(id='foo') # raises Entry.DoesNotExist
The ``DoesNotExist`` exception inherits from
``django.core.exceptions.ObjectDoesNotExist``, so you can target multiple
``DoesNotExist`` exceptions. Example::
from django.core.exceptions import ObjectDoesNotExist
try:
e = Entry.objects.get(id=3)
b = Blog.objects.get(id=1)
except ObjectDoesNotExist:
print "Either the entry or blog doesn't exist."
count()
~~~~~~~
Returns an integer representing the number of objects in the database matching
the ``QuerySet``. ``count()`` never raises exceptions.
Example::
# Returns the total number of entries in the database.
Entry.objects.count()
# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains='Lennon').count()
``count()`` performs a ``SELECT COUNT(*)`` behind the scenes, so you should
always use ``count()`` rather than loading all of the record into Python
objects and calling ``len()`` on the result.
Depending on which database you're using (e.g. PostgreSQL vs. MySQL),
``count()`` may return a long integer instead of a normal Python integer. This
is an underlying implementation quirk that shouldn't pose any real-world
problems.
in_bulk(id_list)
~~~~~~~~~~~~~~~~
Takes a list of primary-key values and returns a dictionary mapping each
primary-key value to an instance of the object with the given ID.
Example::
>>> Blog.objects.in_bulk([1])
{1: Beatles Blog}
>>> Blog.objects.in_bulk([1, 2])
{1: Beatles Blog, 2: Cheddar Talk}
>>> Blog.objects.in_bulk([])
{}
If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary.
latest(field_name=None)
~~~~~~~~~~~~~~~~~~~~~~~
Returns the latest object in the table, by date, using the ``field_name``
provided as the date field.
This example returns the latest ``Entry`` in the table, according to the
``pub_date`` field::
Entry.objects.latest('pub_date')
If your model's ``Meta`` specifies ``get_latest_by``, you can leave off the
``field_name`` argument to ``latest()``. Django will use the field specified in
``get_latest_by`` by default.
Like ``get()``, ``latest()`` raises ``DoesNotExist`` if an object doesn't
exist with the given parameters.
Note ``latest()`` exists purely for convenience and readability.
Field lookups Field lookups
============= -------------
Basic field lookups take the form ``field__lookuptype`` (that's a Field lookups are how you specify the meat of an SQL ``WHERE`` clause. They're
double-underscore). For example:: specified as keyword arguments to the ``QuerySet`` methods ``filter()``,
``exclude()`` and ``get()``.
Poll.objects.filter(pub_date__lte=datetime.now()) Basic lookups keyword arguments take the form ``field__lookuptype=value``.
(That's a double-underscore). For example::
Entry.objects.filter(pub_date__lte='2006-01-01')
translates (roughly) into the following SQL:: translates (roughly) into the following SQL::
SELECT * FROM polls_poll WHERE pub_date <= NOW(); SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
.. admonition:: How this is possible .. admonition:: How this is possible
Python has the ability to define functions that accept arbitrary name-value Python has the ability to define functions that accept arbitrary name-value
arguments whose names and values are evaluated at run time. For more arguments whose names and values are evaluated at runtime. For more
information, see `Keyword Arguments`_ in the official Python tutorial. information, see `Keyword Arguments`_ in the official Python tutorial.
The DB API supports the following lookup types: The database API supports the following lookup types:
exact
~~~~~
Exact match.
Example::
Entry.objects.get(id__exact=14)
SQL equivalent::
SELECT ... WHERE id = 14;
iexact
~~~~~~
Case-insensitive exact match.
Example::
Blog.objects.get(name__iexact='beatles blog')
SQL equivalent::
SELECT ... WHERE name ILIKE 'beatles blog';
Note this will match ``'Beatles Blog'``, ``'beatles blog'``,
``'BeAtLes BLoG'``, etc.
contains
~~~~~~~~
Case-sensitive containment test.
Example::
Entry.objects.get(headline__contains='Lennon')
SQL equivalent::
SELECT ... WHERE headline LIKE '%Lennon%';
Note this will match the headline ``'Today Lennon honored'`` but not
``'today lennon honored'``.
SQLite doesn't support case-sensitive ``LIKE`` statements; ``contains`` acts
like ``icontains`` for SQLite.
icontains
~~~~~~~~~
Case-insensitive containment test.
Example::
Entry.objects.get(headline__icontains='Lennon')
SQL equivalent::
SELECT ... WHERE headline ILIKE '%Lennon%';
gt
~~
Greater than.
Example::
Entry.objects.filter(id__gt=4)
SQL equivalent::
SELECT ... WHERE id > 4;
gte
~~~
Greater than or equal to.
lt
~~
Less than.
lte
~~~
Less than or equal to.
in
~~
In a given list.
Example::
Entry.objects.filter(id__in=[1, 3, 4])
SQL equivalent::
SELECT ... WHERE id IN (1, 3, 4);
startswith
~~~~~~~~~~
Case-sensitive starts-with.
Example::
Entry.objects.filter(headline__startswith='Will')
SQL equivalent::
SELECT ... WHERE headline LIKE 'Will%';
SQLite doesn't support case-sensitive ``LIKE`` statements; ``startswith`` acts
like ``istartswith`` for SQLite.
istartswith
~~~~~~~~~~~
Case-insensitive starts-with.
Example::
Entry.objects.filter(headline__istartswith='will')
SQL equivalent::
SELECT ... WHERE headline ILIKE 'Will%';
endswith
~~~~~~~~
Case-sensitive ends-with.
Example::
Entry.objects.filter(headline__endswith='cats')
SQL equivalent::
SELECT ... WHERE headline LIKE '%cats';
SQLite doesn't support case-sensitive ``LIKE`` statements; ``endswith`` acts
like ``iendswith`` for SQLite.
iendswith
~~~~~~~~~
Case-insensitive ends-with.
Example::
Entry.objects.filter(headline__iendswith='will')
SQL equivalent::
SELECT ... WHERE headline ILIKE '%will'
range
~~~~~
Range test (inclusive).
Example::
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))
SQL equivalent::
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
You can use ``range`` anywhere you can use ``BETWEEN`` in SQL -- for dates,
numbers and even characters.
year
~~~~
For date/datetime fields, exact year match.
Example::
Entry.objects.filter(pub_date__year=2005)
SQL equivalent::
SELECT ... WHERE EXTRACT('year' FROM pub_date) = '2005';
(The exact SQL syntax varies for each database engine.)
TODO: Left off here
=========== ============================================================== =========== ==============================================================
Type Description Type Description
=========== ============================================================== =========== ==============================================================
exact Exact match: ``Poll.objects.get(id__exact=14)`` returns all
polls with an ID of exactly 14.
iexact Case-insensitive exact match:
``Poll.objects.filter(slug__iexact="foo")`` matches a slug of
``foo``, ``FOO``, ``fOo``, etc.
contains Case-sensitive containment test:
``Poll.objects.filter(question__contains="spam")`` returns all polls
that contain "spam" in the question. (PostgreSQL and MySQL
only. SQLite doesn't support case-sensitive LIKE statements;
``contains`` will act like ``icontains`` for SQLite.)
icontains Case-insensitive containment test.
gt Greater than: ``Poll.objects.filter(id__gt=4)``.
gte Greater than or equal to.
lt Less than.
lte Less than or equal to.
in In a given list: ``Poll.objects.filter(id__in=[1, 3, 4])`` returns
a list of polls whose IDs are either 1, 3 or 4.
startswith Case-sensitive starts-with:
``Poll.objects.filter(question__startswith="Would")``. (PostgreSQL
and MySQL only. SQLite doesn't support case-sensitive LIKE
statements; ``startswith`` will act like ``istartswith`` for
SQLite.)
endswith Case-sensitive ends-with. (PostgreSQL and MySQL only.)
istartswith Case-insensitive starts-with.
iendswith Case-insensitive ends-with.
range Range test:
``Poll.objects.filter(pub_date__range=(start_date, end_date))``
returns all polls with a pub_date between ``start_date``
and ``end_date`` (inclusive).
year For date/datetime fields, exact year match:
``Poll.objects.count(pub_date__year=2005)``.
month For date/datetime fields, exact month match. month For date/datetime fields, exact month match.
day For date/datetime fields, exact day match. day For date/datetime fields, exact day match.
isnull True/False; does is IF NULL/IF NOT NULL lookup: isnull True/False; does is IF NULL/IF NOT NULL lookup:
``Poll.objects.filter(expire_date__isnull=True)``. ``Poll.objects.filter(expire_date__isnull=True)``.
=========== ============================================================== =========== ==============================================================
Escaping parenthesis and underscores in LIKE statements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As you may expect,
If no lookup type is provided, a type of ``exact`` is assumed. The following If no lookup type is provided, a type of ``exact`` is assumed. The following
two statements are equivalent:: two statements are equivalent::
@ -697,6 +1005,45 @@ If you pass an invalid keyword argument, the function will raise ``TypeError``.
.. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000 .. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000
Caching and QuerySets
---------------------
Each ``QuerySet`` contains a cache, to minimize database access. It's important
to understand how it works, in order to write the most efficient code.
In a newly created ``QuerySet``, the cache is empty. The first time a
``QuerySet`` is evaluated -- and, hence, a database query happens -- Django
saves the query results in the ``QuerySet``'s cache and returns the results
that have been explicitly requested (e.g., the next element, if the
``QuerySet`` is being iterated over). Subsequent evaluations of the
``QuerySet`` reuse the cached results.
Keep this caching behavior in mind, because it may bite you if you don't use
your ``QuerySet``s correctly. For example, the following will create two
``QuerySet``s, evaluate them, and throw them away::
print [e.headline for e in Entry.objects.all()]
print [e.pub_date for e in Entry.objects.all()]
That means the same database query will be executed twice, effectively doubling
your database load. Also, there's a possibility the two lists may not include
the same database records, because an ``Entry`` may have been added or deleted
in the split second between the two requests.
To avoid this problem, simply save the ``QuerySet`` and reuse it::
queryset = Poll.objects.all()
print [p.headline for p in queryset] # Evaluate the query set.
print [p.pub_date for p in queryset] # Re-use the cache from the evaluation.
Deleting objects
================
OR lookups OR lookups
========== ==========
@ -772,54 +1119,6 @@ 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/
Specialist QuerySet evaluation
==============================
The following specialist functions can also be used to evaluate a Query Set.
Unlike iteration or slicing, these methods do not populate the cache; each
time one of these evaluation functions is used, the database will be queried.
``get(**kwargs)``
-----------------
Returns the object matching the given lookup parameters, which should be in
the format described in _`Field lookups`. Raises a module-level
``DoesNotExist`` exception if an object wasn't found for the given parameters.
Raises ``AssertionError`` if more than one object was found.
``count()``
-----------
Returns an integer representing the number of objects in the database matching
the Query Set. ``count()`` never raises exceptions.
Depending on which database you're using (e.g. PostgreSQL vs. MySQL), this may
return a long integer instead of a normal Python integer.
``in_bulk(id_list)``
--------------------
Takes a list of IDs and returns a dictionary mapping each ID to an instance of
the object with the given ID. For example::
>>> Poll.objects.in_bulk([1])
{1: What's up?}
>>> Poll.objects.in_bulk([1, 2])
{1: What's up?, 2: What's your name?}
>>> Poll.objects.in_bulk([])
{}
``latest(field_name=None)``
---------------------------
Returns the latest object, according to the model's 'get_latest_by'
Meta option, or using the field_name provided. For example::
>>> Poll.objects.latest()
What's up?
>>> Poll.objects.latest('expire_date')
What's your name?
Relationships (joins) Relationships (joins)
===================== =====================