diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2006-05-02 01:31:56 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2006-05-02 01:31:56 +0000 |
| commit | f69cf70ed813a8cd7e1f963a14ae39103e8d5265 (patch) | |
| tree | d3b32e84cd66573b3833ddf662af020f8ef2f7a8 /docs/db-api.txt | |
| parent | d5dbeaa9be359a4c794885c2e9f1b5a7e5e51fb8 (diff) | |
MERGED MAGIC-REMOVAL BRANCH TO TRUNK. This change is highly backwards-incompatible. Please read http://code.djangoproject.com/wiki/RemovingTheMagic for upgrade instructions.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2809 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/db-api.txt')
| -rw-r--r-- | docs/db-api.txt | 1648 |
1 files changed, 1228 insertions, 420 deletions
diff --git a/docs/db-api.txt b/docs/db-api.txt index e37645e601..8da6ebbac2 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -2,509 +2,1366 @@ Database API reference ====================== -Once you've created your `data models`_, you'll need to retrieve data from the -database. This document explains the database abstraction API derived from the -models, and how to create, retrieve and update objects. +Once you've created your `data models`_, Django automatically gives you a +database-abstraction API that lets you create, retrieve, update and delete +objects. This document explains that API. .. _`data models`: http://www.djangoproject.com/documentation/model_api/ -Throughout this reference, we'll refer to the following Poll application:: +Throughout this reference, we'll refer to the following models, which comprise +a weblog application:: - class Poll(meta.Model): - slug = meta.SlugField(unique_for_month='pub_date') - question = meta.CharField(maxlength=255) - pub_date = meta.DateTimeField() - expire_date = meta.DateTimeField() + class Blog(models.Model): + name = models.CharField(maxlength=100) + tagline = models.TextField() - def __repr__(self): - return self.question + def __str__(self): + return self.name - class Choice(meta.Model): - poll = meta.ForeignKey(Poll, edit_inline=meta.TABULAR, - num_in_admin=10, min_num_in_admin=5) - choice = meta.CharField(maxlength=255, core=True) - votes = meta.IntegerField(editable=False, default=0) + class Author(models.Model): + name = models.CharField(maxlength=50) + email = models.URLField() - def __repr__(self): - return self.choice + class __str__(self): + return self.name -Basic lookup functions -====================== + class Entry(models.Model): + blog = models.ForeignKey(Blog) + headline = models.CharField(maxlength=255) + body_text = models.TextField() + pub_date = models.DateTimeField() + authors = models.ManyToManyField(Author) -Each model exposes these module-level functions for lookups: + def __str__(self): + return self.headline -get_object(\**kwargs) ---------------------- +Creating objects +================ -Returns the object matching the given lookup parameters, which should be in -the format described in "Field lookups" below. 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. +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. -get_list(\**kwargs) -------------------- +To create an object, instantiate it using keyword arguments to the model class, +then call ``save()`` to save it to the database. -Returns a list of objects matching the given lookup parameters, which should be -in the format described in "Field lookups" below. If no objects match the given -parameters, it returns an empty list. ``get_list()`` will always return a list. +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.) -get_iterator(\**kwargs) ------------------------ +Assuming models live in a file ``mysite/blog/models.py``, here's an example:: -Just like ``get_list()``, except it returns an iterator instead of a list. This -is more efficient for large result sets. This example shows the difference:: + from mysite.blog.models import Blog + b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') + b.save() - # get_list() loads all objects into memory. - for obj in foos.get_list(): - print repr(obj) +This performs an ``INSERT`` SQL statement behind the scenes. Django doesn't hit +the database until you explicitly call ``save()``. - # get_iterator() only loads a number of objects into memory at a time. - for obj in foos.get_iterator(): - print repr(obj) +The ``save()`` method has no return value. -get_count(\**kwargs) --------------------- +Auto-incrementing primary keys +------------------------------ -Returns an integer representing the number of objects in the database matching -the given lookup parameters, which should be in the format described in -"Field lookups" below. ``get_count()`` never raises exceptions +If a model has an ``AutoField`` -- an auto-incrementing primary key -- then +that auto-incremented value will be calculated and saved as an attribute on +your object the first time you call ``save()``. -Depending on which database you're using (e.g. PostgreSQL vs. MySQL), this may -return a long integer instead of a normal Python integer. +Example:: -get_values(\**kwargs) ---------------------- + b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.') + b2.id # Returns None, because b doesn't have an ID yet. + b2.save() + b2.id # Returns the ID of your new object. -Just like ``get_list()``, except it returns a list of dictionaries instead of -model-instance objects. +There's no way to tell what the value of an ID will be before you call +``save()``, because that value is calculated by your database, not by Django. -It accepts an optional parameter, ``fields``, which should be a list or tuple -of field names. If you don't specify ``fields``, each dictionary in the list -returned by ``get_values()`` will have a key and value for each field in the -database table. If you specify ``fields``, each dictionary will have only the -field keys/values for the fields you specify. Here's an example, using the -``Poll`` model defined above:: +(For convenience, each model has an ``AutoField`` named ``id`` by default +unless you explicitly specify ``primary_key=True`` on a field. See the +`AutoField documentation`_.) - >>> from datetime import datetime - >>> p1 = polls.Poll(slug='whatsup', question="What's up?", - ... pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20)) - >>> p1.save() - >>> p2 = polls.Poll(slug='name', question="What's your name?", - ... pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20)) - >>> p2.save() - >>> polls.get_list() - [What's up?, What's your name?] - >>> polls.get_values() - [{'id': 1, 'slug': 'whatsup', 'question': "What's up?", 'pub_date': datetime.datetime(2005, 2, 20), 'expire_date': datetime.datetime(2005, 3, 20)}, - {'id': 2, 'slug': 'name', 'question': "What's your name?", 'pub_date': datetime.datetime(2005, 3, 20), 'expire_date': datetime.datetime(2005, 4, 20)}] - >>> polls.get_values(fields=['id', 'slug']) - [{'id': 1, 'slug': 'whatsup'}, {'id': 2, 'slug': 'name'}] +.. _AutoField documentation: TODO: Link -Use ``get_values()`` when you know you're only going to need a couple of field -values and you won't need the functionality of a model instance object. It's -more efficient to select only the fields you need to use. +Explicitly specifying auto-primary-key values +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -get_values_iterator(\**kwargs) ------------------------------- +If a model has an ``AutoField`` but you want to define a new object's ID +explicitly when saving, just define it explicitly before saving, rather than +relying on the auto-assignment of the ID. -Just like ``get_values()``, except it returns an iterator instead of a list. -See the section on ``get_iterator()`` above. +Example:: -get_in_bulk(id_list, \**kwargs) -------------------------------- + b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.') + b3.id # Returns 3. + b3.save() + b3.id # Returns 3. -Takes a list of IDs and returns a dictionary mapping each ID to an instance of -the object with the given ID. Also takes optional keyword lookup arguments, -which should be in the format described in "Field lookups" below. Here's an -example, using the ``Poll`` model defined above:: +If you assign auto-primary-key values manually, make sure not to use an +already-existing primary-key value! If you create a new object with an explicit +primary-key value that already exists in the database, Django will assume +you're changing the existing record rather than creating a new one. - >>> from datetime import datetime - >>> p1 = polls.Poll(slug='whatsup', question="What's up?", - ... pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20)) - >>> p1.save() - >>> p2 = polls.Poll(slug='name', question="What's your name?", - ... pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20)) - >>> p2.save() - >>> polls.get_list() - [What's up?, What's your name?] - >>> polls.get_in_bulk([1]) - {1: What's up?} - >>> polls.get_in_bulk([1, 2]) - {1: What's up?, 2: What's your name?} +Given the above ``'Cheddar Talk'`` blog example, this example would override +the previous record in the database:: -Field lookups -============= + b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.') + b4.save() # Overrides the previous blog with ID=3! -Basic field lookups take the form ``field__lookuptype`` (that's a -double-underscore). For example:: +See _`How Django knows to UPDATE vs. INSERT`, below, for the reason this +happens. - polls.get_list(pub_date__lte=datetime.datetime.now()) +Explicitly specifying auto-primary-key values is mostly useful for bulk-saving +objects, when you're confident you won't have primary-key collision. -translates (roughly) into the following SQL:: +Saving changes to objects +========================= - SELECT * FROM polls_polls WHERE pub_date <= NOW(); +To save changes to an object that's already in the database, use ``save()``. -.. admonition:: How this is possible +Given a ``Blog`` instance ``b5`` that has already been saved to the database, +this example changes its name and updates its record in the database:: - Python has the ability to define functions that accept arbitrary name-value - arguments whose names and values are evaluated at run time. For more - information, see `Keyword Arguments`_ in the official Python tutorial. + b5.name = 'New name' + b5.save() -The DB API supports the following lookup types: +This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit +the database until you explicitly call ``save()``. - =========== ============================================================== - Type Description - =========== ============================================================== - exact Exact match: ``polls.get_object(id__exact=14)``. - iexact Case-insensitive exact match: - ``polls.get_list(slug__iexact="foo")`` matches a slug of - ``foo``, ``FOO``, ``fOo``, etc. - contains Case-sensitive containment test: - ``polls.get_list(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: ``polls.get_list(id__gt=4)``. - gte Greater than or equal to. - lt Less than. - lte Less than or equal to. - ne Not equal to. - in In a given list: ``polls.get_list(id__in=[1, 3, 4])`` returns - a list of polls whose IDs are either 1, 3 or 4. - startswith Case-sensitive starts-with: - ``polls.get_list(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: - ``polls.get_list(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: - ``polls.get_count(pub_date__year=2005)``. - month For date/datetime fields, exact month match. - day For date/datetime fields, exact day match. - isnull True/False; does is IF NULL/IF NOT NULL lookup: - ``polls.get_list(expire_date__isnull=True)``. - =========== ============================================================== +The ``save()`` method has no return value. -Multiple lookups are allowed, of course, and are translated as "AND"s:: +How Django knows to UPDATE vs. INSERT +------------------------------------- - polls.get_list( - pub_date__year=2005, - pub_date__month=1, - question__startswith="Would", - ) +You may have noticed Django database objects use the same ``save()`` method +for creating and changing objects. Django abstracts the need to use ``INSERT`` +or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django +follows this algorithm: -...retrieves all polls published in January 2005 that have a question starting with "Would." + * 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 + already exists. + * If the record with the given primary key does already exist, Django + executes an ``UPDATE`` query. + * If the object's primary key attribute is *not* set, or if it's set but a + record doesn't exist, Django executes an ``INSERT``. -For convenience, there's a ``pk`` lookup type, which translates into -``(primary_key)__exact``. In the polls example, these two statements are -equivalent:: +The one gotcha here is that you should be careful not to specify a primary-key +value explicitly when saving new objects, if you cannot guarantee the +primary-key value is unused. For more on this nuance, see +"Explicitly specifying auto-primary-key values" above. - polls.get_object(id__exact=3) - polls.get_object(pk=3) +Retrieving objects +================== -``pk`` lookups also work across joins. In the polls example, these two -statements are equivalent:: +To retrieve objects from your database, you construct a ``QuerySet`` via a +``Manager`` on your model class. - choices.get_list(poll__id__exact=3) - choices.get_list(poll__pk=3) +A ``QuerySet`` represents a collection of objects from your database. It can +have zero, one or many *filters* -- criteria that narrow down the collection +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``. -If you pass an invalid keyword argument, the function will raise ``TypeError``. +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 +directly via the model class, like so:: -.. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000 + Blog.objects # <django.db.models.manager.Manager object at ...> + b = Blog(name='Foo', tagline='Bar') + b.objects # AttributeError: "Manager isn't accessible via Blog instances." -OR lookups ----------- +(``Managers`` are accessible only via model classes, rather than from model +instances, to enforce a separation between "table-level" operations and +"record-level" operations.) + +The ``Manager`` is the main source of ``QuerySets`` for a model. It acts as a +"root" ``QuerySet`` that describes all objects in the model's database table. +For example, ``Blog.objects`` is the initial ``QuerySet`` that contains all +``Blog`` objects in the database. -By default, multiple lookups are "AND"ed together. If you'd like to use ``OR`` -statements in your queries, use the ``complex`` lookup type. +Retrieving all objects +---------------------- -``complex`` takes an expression of clauses, each of which is an instance of -``django.core.meta.Q``. ``Q`` takes an arbitrary number of keyword arguments in -the standard Django lookup format. And you can use Python's "and" (``&``) and -"or" (``|``) operators to combine ``Q`` instances. For example:: +The simplest way to retrieve objects from a table is to get all of them. +To do this, use the ``all()`` method on a ``Manager``. - from django.core.meta import Q - polls.get_object(complex=(Q(question__startswith='Who') | Q(question__startswith='What'))) +Example:: + + all_entries = Entry.objects.all() + +The ``all()`` method returns a ``QuerySet`` of all the objects in the database. + +(If ``Entry.objects`` is a ``QuerySet``, why can't we just do ``Entry.objects``? +That's because ``Entry.objects``, the root ``QuerySet``, is a special case +that cannot be evaluated. The ``all()`` method returns a ``QuerySet`` that +*can* be evaluated.) + +Filtering objects +----------------- -The ``|`` symbol signifies an "OR", so this (roughly) translates into:: +The root ``QuerySet`` provided by the ``Manager`` describes all objects in the +database table. Usually, though, you'll need to select only a subset of the +complete set of objects. - SELECT * FROM polls - WHERE question LIKE 'Who%' OR question LIKE 'What%'; +To create such a subset, you refine the initial ``QuerySet``, adding filter +conditions. The two most common ways to refine a ``QuerySet`` are: + +``filter(**kwargs)`` + Returns a new ``QuerySet`` containing objects that match the given lookup + parameters. + +``exclude(**kwargs)`` + Returns a new ``QuerySet`` containing objects that do *not* match the given + lookup parameters. + +The lookup parameters (``**kwargs`` in the above function definitions) should +be in the format described in _`Field lookups` below. + +For example, to get a ``QuerySet`` of blog entries from the year 2006, use +``filter()`` like so:: + + Entry.objects.filter(pub_date__year=2006) + +(Note we don't have to add an ``all()`` -- ``Entry.objects.all().filter(...)``. +That would still work, but you only need ``all()`` when you want all objects +from the root ``QuerySet``.) + +Chaining filters +~~~~~~~~~~~~~~~~ + +The result of refining a ``QuerySet`` is itself a ``QuerySet``, so it's +possible to chain refinements together. For example:: + + Entry.objects.filter( + headline__startswith='What').exclude( + pub_date__gte=datetime.now()).filter( + pub_date__gte=datetime(2005, 1, 1)) + +...takes the initial ``QuerySet`` of all entries in the database, adds a +filter, then an exclusion, then another filter. The final result is a +``QuerySet`` containing all entries with a headline that starts with "What", +that were published between January 1, 2005, and the current day. + +Filtered QuerySets are unique +----------------------------- + +Each time you refine a ``QuerySet``, you get a brand-new ``QuerySet`` that is +in no way bound to the previous ``QuerySet``. Each refinement creates a +separate and distinct ``QuerySet`` that can be stored, used and reused. -You can use ``&`` and ``|`` operators together, and use parenthetical grouping. Example:: - polls.get_object(complex=(Q(question__startswith='Who') & (Q(pub_date__exact=date(2005, 5, 2)) | Q(pub_date__exact=date(2005, 5, 6)))) + q1 = Entry.objects.filter(headline__startswith="What") + q2 = q1.exclude(pub_date__gte=datetime.now()) + q3 = q1.filter(pub_date__gte=datetime.now()) -This roughly translates into:: +These three ``QuerySets`` are separate. The first is a base ``QuerySet`` +containing all entries that contain a headline starting with "What". The second +is a subset of the first, with an additional criteria that excludes records +whose ``pub_date`` is greater than now. The third is a subset of the first, +with an additional criteria that selects only the records whose ``pub_date`` is +greater than now. The initial ``QuerySet`` (``q1``) is unaffected by the +refinement process. - SELECT * FROM polls - WHERE question LIKE 'Who%' - AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06'); +QuerySets are lazy +------------------ -See the `OR lookups examples page`_ for more examples. +``QuerySets`` are lazy -- the act of creating a ``QuerySet`` doesn't involve +any database activity. You can stack filters together all day long, and Django +won't actually run the query until the ``QuerySet`` is *evaluated*. -.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/ +When QuerySets are evaluated +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Ordering -======== +You can evaluate a ``QuerySet`` in the following ways: -The results are automatically ordered by the ordering tuple given by the -``ordering`` key in the model, but the ordering may be explicitly -provided by the ``order_by`` argument to a lookup:: + * **Iteration.** A ``QuerySet`` is iterable, and it executes its database + query the first time you iterate over it. For example, this will print + the headline of all entries in the database:: - polls.get_list( - pub_date__year=2005, - pub_date__month=1, - order_by=('-pub_date', 'question'), - ) + for e in Entry.objects.all(): + print e.headline + + * **Slicing.** A ``QuerySet`` can be sliced, using Python's array-slicing + syntax, and it executes its database query the first time you slice it. + Examples:: + + fifth_entry = Entry.objects.all()[4] + all_entries_but_the_first_two = Entry.objects.all()[2:] + every_second_entry = Entry.objects.all()[::2] + + * **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it. + This is for convenience in the Python interactive interpreter, so you can + immediately see your results when using the API interactively. + + * **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it. + This, as you might expect, returns the length of the result list. + + Note: *Don't* use ``len()`` on ``QuerySet``s if all you want to do is + determine the number of records in the set. It's much more efficient to + handle a count at the database level, using SQL's ``SELECT COUNT(*)``, + and Django provides a ``count()`` method for precisely this reason. See + ``count()`` below. + + * **list().** Force evaluation of a ``QuerySet`` by calling ``list()`` on + it. For example:: + + entry_list = list(Entry.objects.all()) + + Be warned, though, that this could have a large memory overhead, because + Django will load each element of the list into memory. In contrast, + iterating over a ``QuerySet`` will take advantage of your database to + load data and instantiate objects only as you need them. + +QuerySet methods that return new QuerySets +------------------------------------------ -The result set above will be ordered by ``pub_date`` descending, then -by ``question`` ascending. The negative sign in front of "-pub_date" indicates -descending order. Ascending order is implied. To order randomly, use "?", like -so:: +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 +executed. - polls.get_list(order_by=['?']) +filter(**kwargs) +~~~~~~~~~~~~~~~~ + +Returns a new ``QuerySet`` containing objects that match the given lookup +parameters. + +The lookup parameters (``**kwargs``) should be in the format described in +_`Field lookups` below. Multiple parameters are joined via ``AND`` in the +underlying SQL statement. + +exclude(**kwargs) +~~~~~~~~~~~~~~~~~ + +Returns a new ``QuerySet`` containing objects that do *not* match the given +lookup parameters. + +The lookup parameters (``**kwargs``) should be in the format described in +_`Field lookups` below. Multiple parameters are joined via ``AND`` in the +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 +AND whose ``headline`` is "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 +OR whose ``headline`` is "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. + +order_by(*fields) +~~~~~~~~~~~~~~~~~ + +By default, results returned by a ``QuerySet`` are ordered by the ordering +tuple given by the ``ordering`` option in the model's ``Meta``. You can +override this on a per-``QuerySet`` basis by using the ``order_by`` method. + +Example:: + + Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline') + +The result above will be ordered by ``pub_date`` descending, then by +``headline`` ascending. The negative sign in front of ``"-pub_date"`` indicates +*descending* order. Ascending order is implied. To order randomly, use ``"?"``, +like so:: + + Entry.objects.order_by('?') To order by a field in a different table, add the other table's name and a dot, like so:: - choices.get_list(order_by=('polls.pub_date', 'choice')) + Entry.objects.order_by('blogs_blog.name', 'headline') 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. -Relationships (joins) -===================== +distinct() +~~~~~~~~~~ -Joins may implicitly be performed by following relationships: -``choices.get_list(poll__slug__exact="eggs")`` fetches a list of ``Choice`` -objects where the associated ``Poll`` has a slug of ``eggs``. Multiple levels -of joins are allowed. +Returns a new ``QuerySet`` that uses ``SELECT DISTINCT`` in its SQL query. This +eliminates duplicate rows from the query results. -Given an instance of an object, related objects can be looked-up directly using -convenience functions. For example, if ``p`` is a ``Poll`` instance, -``p.get_choice_list()`` will return a list of all associated choices. Astute -readers will note that this is the same as -``choices.get_list(poll__id__exact=p.id)``, except clearer. +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. -Each type of relationship creates a set of methods on each object in the -relationship. These methods are created in both directions, so objects that are -"related-to" need not explicitly define reverse relationships; that happens -automatically. +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()``. -One-to-one relations --------------------- +values(*fields) +~~~~~~~~~~~~~~~ -Each object in a one-to-one relationship will have a ``get_relatedobjectname()`` -method. For example:: +Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of +dictionaries instead of model-instance objects. - class Place(meta.Model): - # ... +Each of those dictionaries represents an object, with the keys corresponding to +the attribute names of model objects. - class Restaurant(meta.Model): - # ... - the_place = meta.OneToOneField(places.Place) +This example compares the dictionaries of ``values()`` with the normal model +objects:: -In the above example, each ``Place`` will have a ``get_restaurant()`` method, -and each ``Restaurant`` will have a ``get_the_place()`` method. + # This list contains a Blog object. + >>> Blog.objects.filter(name__startswith='Beatles') + [Beatles Blog] -Many-to-one relations ---------------------- + # This list contains a dictionary. + >>> Blog.objects.filter(name__startswith='Beatles').values() + [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}] -In each many-to-one relationship, the related object will have a -``get_relatedobject()`` method, and the related-to object will have -``get_relatedobject()``, ``get_relatedobject_list()``, and -``get_relatedobject_count()`` methods (the same as the module-level -``get_object()``, ``get_list()``, and ``get_count()`` methods). +``values()`` takes optional positional arguments, ``*fields``, which specify +field names to which the ``SELECT`` should be limited. If you specify the +fields, each dictionary will contain only the field keys/values for the fields +you specify. If you don't specify the fields, each dictionary will contain a +key and value for every field in the database table. -In the poll example above, here are the available choice methods on a ``Poll`` object ``p``:: +Example:: - p.get_choice() - p.get_choice_list() - p.get_choice_count() + >>> Blog.objects.values() + [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}], + >>> Blog.objects.values('id', 'name') + [{'id': 1, 'name': 'Beatles Blog'}] -And a ``Choice`` object ``c`` has the following method:: +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 +the fields you need to use. - c.get_poll() +Finally, note a ``ValuesQuerySet`` is a subclass of ``QuerySet``, so it has all +methods of ``QuerySet``. You can call ``filter()`` on it, or ``order_by()``, or +whatever. Yes, that means these two calls are identical:: -Many-to-many relations ----------------------- + Blog.objects.values().order_by('id') + Blog.objects.order_by('id').values() + +The people who made Django prefer to put all the SQL-affecting methods first, +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. + +dates(field, kind, order='ASC') +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Returns a ``DateQuerySet`` -- a ``QuerySet`` that evaluates to a list of +``datetime.datetime`` objects representing all available dates of a particular +kind within the contents of the ``QuerySet``. + +``field`` should be the name of a ``DateField`` or ``DateTimeField`` of your +model. + +``kind`` should be either ``"year"``, ``"month"`` or ``"day"``. Each +``datetime.datetime`` object in the result list is "truncated" to the given +``type``. + + * ``"year"`` returns a list of all distinct year 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. + +``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or +``'DESC'``. This specifies how to order the results. + +Examples:: -Many-to-many relations result in the same set of methods as `Many-to-one relations`_, -except that the ``get_relatedobject_list()`` function on the related object will -return a list of instances instead of a single instance. So, if the relationship -between ``Poll`` and ``Choice`` was many-to-many, ``choice.get_poll_list()`` would -return a list. + >>> Entry.objects.dates('pub_date', 'year') + [datetime.datetime(2005, 1, 1)] + >>> Entry.objects.dates('pub_date', 'month') + [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)] + >>> Entry.objects.dates('pub_date', 'day') + [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)] + >>> Entry.objects.dates('pub_date', 'day', order='DESC') + [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)] + >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') + [datetime.datetime(2005, 3, 20)] -Relationships across applications ---------------------------------- +select_related() +~~~~~~~~~~~~~~~~ -If a relation spans applications -- if ``Place`` was had a ManyToOne relation to -a ``geo.City`` object, for example -- the name of the other application will be -added to the method, i.e. ``place.get_geo_city()`` and -``city.get_places_place_list()``. +Returns a ``QuerySet`` that will automatically "follow" foreign-key +relationships, selecting that additional related-object data when it executes +its query. This is a performance booster which results in (sometimes much) +larger queries but means later use of foreign-key relationships won't require +database queries. -Selecting related objects -------------------------- +The following examples illustrate the difference between plain lookups and +``select_related()`` lookups. Here's standard lookup:: -Relations are the bread and butter of databases, so there's an option to "follow" -all relationships and pre-fill them in a simple cache so that later calls to -objects with a one-to-many relationship don't have to hit the database. Do this by -passing ``select_related=True`` to a lookup. This results in (sometimes much) larger -queries, but it means that later use of relationships is much faster. + # Hits the database. + e = Entry.objects.get(id=5) -For example, using the Poll and Choice models from above, if you do the following:: + # Hits the database again to get the related Blog object. + b = e.blog - c = choices.get_object(id__exact=5, select_related=True) +And here's ``select_related`` lookup:: -Then subsequent calls to ``c.get_poll()`` won't hit the database. + # Hits the database. + e = Entry.objects.select_related().get(id=5) -Note that ``select_related`` follows foreign keys as far as possible. If you have the + # 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:: - class Poll(meta.Model): + class City(models.Model): # ... - class Choice(meta.Model): + class Person(models.Model): # ... - poll = meta.ForeignKey(Poll) + hometown = models.ForeignKey(City) - class SingleVote(meta.Model): + class Book(meta.Model): # ... - choice = meta.ForeignKey(Choice) + author = models.ForeignKey(Person) -then a call to ``singlevotes.get_object(id__exact=4, select_related=True)`` will -cache the related choice *and* the related poll:: +...then a call to ``Book.objects.select_related().get(id=4)`` will cache the +related ``Person`` *and* the related ``City``:: - >>> sv = singlevotes.get_object(id__exact=4, select_related=True) - >>> c = sv.get_choice() # Doesn't hit the database. - >>> p = c.get_poll() # Doesn't hit the database. + b = Book.objects.select_related().get(id=4) + p = b.author # Doesn't hit the database. + c = p.hometown # Doesn't hit the database. - >>> sv = singlevotes.get_object(id__exact=4) # Note no "select_related". - >>> c = sv.get_choice() # Hits the database. - >>> p = c.get_poll() # Hits the database. + sv = Book.objects.get(id=4) # No select_related() in this example. + p = b.author # Hits the database. + c = p.hometown # Hits the database. -Limiting selected rows -====================== +extra(select=None, where=None, params=None, tables=None) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +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``. + +By definition, these extra lookups may not be portable to different database +engines (because you're explicitly writing SQL code) and violate the DRY +principle, so you should avoid them if possible. + +Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None +of the arguments is required, but you should use at least one of them. + +``select`` + The ``select`` argument lets you put extra fields in the ``SELECT`` clause. + It should be a dictionary mapping attribute names to SQL clauses to use to + calculate that attribute. + + Example:: + + Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) -The ``limit``, ``offset``, and ``distinct`` keywords can be used to control -which rows are returned. Both ``limit`` and ``offset`` should be integers which -will be directly passed to the SQL ``LIMIT``/``OFFSET`` commands. + 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. -If ``distinct`` is True, only distinct rows will be returned. This is equivalent -to a ``SELECT DISTINCT`` SQL clause. You can use this with ``get_values()`` to -get distinct values. For example, this returns the distinct first_names:: + Django inserts the given SQL snippet directly into the ``SELECT`` + statement, so the resulting SQL of the above example would be:: - >>> people.get_values(fields=['first_name'], distinct=True) - [{'first_name': 'Adrian'}, {'first_name': 'Jacob'}, {'first_name': 'Simon'}] + SELECT blog_entry.*, (pub_date > '2006-01-01') + FROM blog_entry; -Other lookup options -==================== -There are a few other ways of more directly controlling the generated SQL -for the lookup. Note that by definition these extra lookups may not be -portable to different database engines (because you're explicitly writing -SQL code) and should be avoided if possible.: + 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={ + 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id' + }, + ) + + (In this particular case, we're exploiting the fact that the query will + already contain the ``blog_blog`` table in its ``FROM`` clause.) + + 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`` + You can define explicit SQL ``WHERE`` clauses -- perhaps to perform + non-explicit joins -- by using ``where``. You can manually add tables to + the SQL ``FROM`` clause by using ``tables``. + + ``where`` and ``tables`` both take a list of strings. All ``where`` + parameters are "AND"ed to any other search criteria. + + Example:: + + Entry.objects.extra(where=['id IN (3, 4, 5, 20)']) + + ...translates (roughly) into the following SQL:: + + 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. -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. + Example:: -``select`` ----------- + 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.) + + Bad:: + + Entry.objects.extra(where=["headline='Lennon'"]) + + Good:: + + Entry.objects.extra(where=['headline=%s'], params=['Lennon']) + +QuerySet methods that do not return QuerySets +--------------------------------------------- + +The following ``QuerySet`` methods evaluate the ``QuerySet`` and return +something *other than* a ``QuerySet``. + +These methods do not use a cache (see _`Caching and QuerySets` below). Rather, +they query the database each time they're called. + +get(**kwargs) +~~~~~~~~~~~~~ + +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 are how you specify the meat of an SQL ``WHERE`` clause. They're +specified as keyword arguments to the ``QuerySet`` methods ``filter()``, +``exclude()`` and ``get()``. + +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:: + + SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; + +.. admonition:: How this is possible + + Python has the ability to define functions that accept arbitrary name-value + arguments whose names and values are evaluated at runtime. For more + information, see `Keyword Arguments`_ in the official Python tutorial. + + .. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000 + +If you pass an invalid keyword argument, a lookup function will raise +``TypeError``. + +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; -The ``select`` keyword allows you to select extra fields. This should be a -dictionary mapping attribute names to a SQL clause to use to calculate that -attribute. For example:: +gte +~~~ - polls.get_list( - select={ - 'choice_count': 'SELECT COUNT(*) FROM choices WHERE poll_id = polls.id' - } +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. Takes a four-digit year. + +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.) + +month +~~~~~ + +For date/datetime fields, exact month match. Takes an integer 1 (January) +through 12 (December). + +Example:: + + Entry.objects.filter(pub_date__month=12) + +SQL equivalent:: + + SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12'; + +(The exact SQL syntax varies for each database engine.) + +day +~~~ + +For date/datetime fields, exact day match. + +Example:: + + Entry.objects.filter(pub_date__day=3) + +SQL equivalent:: + + SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3'; + +(The exact SQL syntax varies for each database engine.) + +Note this will match any record with a pub_date on the third day of the month, +such as January 3, July 3, etc. + +isnull +~~~~~~ + +``NULL`` or ``IS NOT NULL`` match. Takes either ``True`` or ``False``, which +correspond to ``IS NULL`` and ``IS NOT NULL``, respectively. + +Example:: + + Entry.objects.filter(pub_date__isnull=True) + +SQL equivalent:: + + SELECT ... WHERE pub_date IS NULL; + +Default lookups are exact +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you don't provide a lookup type -- that is, if your keyword argument doesn't +contain a double underscore -- the lookup type is assumed to be ``exact``. + +For example, the following two statements are equivalent:: + + Blog.objects.get(id=14) + Blog.objects.get(id__exact=14) + +This is for convenience, because ``exact`` lookups are the common case. + +The pk lookup shortcut +~~~~~~~~~~~~~~~~~~~~~~ + +For convenience, Django provides a ``pk`` lookup type, which stands for +"primary_key". This is shorthand for "an exact lookup on the primary-key." + +In the example ``Blog`` model, the primary key is the ``id`` field, so these +two statements are equivalent:: + + Blog.objects.get(id__exact=14) + Blog.objects.get(pk=14) + +``pk`` lookups also work across joins. For example, these two statements are +equivalent:: + + Entry.objects.filter(blog__id__exact=3) + Entry.objects.filter(blog__pk=3) + +Escaping parenthesis and underscores in LIKE statements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The field lookups that equate to ``LIKE`` SQL statements (``iexact``, +``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith`` +and ``iendswith``) will automatically escape the two special characters used in +``LIKE`` statements -- the percent sign and the underscore. (In a ``LIKE`` +statement, the percent sign signifies a multiple-character wildcard and the +underscore signifies a single-character wildcard.) + +This means things should work intuitively, so the abstraction doesn't leak. +For example, to retrieve all the entries that contain a percent sign, just use +the percent sign as any other character:: + + Entry.objects.filter(headline__contains='%') + +Django takes care of the quoting for you; the resulting SQL will look something +like this:: + + SELECT ... WHERE headline LIKE '%\%%'; + +Same goes for underscores. Both percentage signs and underscores are handled +for you transparently. + +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. + +Comparing objects +================= + +To compare two model instances, just use the standard Python comparison operator, +the double equals sign: ``==``. Behind the scenes, that compares the primary +key values of two models. + +Using the ``Entry`` example above, the following two statements are equivalent:: + + some_entry == other_entry + some_entry.id == other_entry.id + +If a model's primary key isn't called ``id``, no problem. Comparisons will +always use the primary key, whatever it's called. For example, if a model's +primary key field is called ``name``, these two statements are equivalent:: + + some_obj == other_obj + some_obj.name == other_obj.name + + + + +======================================== +THE REST OF THIS HAS NOT YET BEEN EDITED +======================================== + + +OR lookups +========== + +Keyword argument queries are "AND"ed together. If you have more +complex query requirements (for example, you need to include an ``OR`` +statement in your query), you need to use ``Q`` objects. + +A ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a +collection of keyword arguments. These keyword arguments are specified in +the same way as keyword arguments to the basic lookup functions like get() +and filter(). For example:: + + Q(question__startswith='What') + +is a ``Q`` object encapsulating a single ``LIKE`` query. ``Q`` objects can be +combined using the ``&`` and ``|`` operators. When an operator is used on two +``Q`` objects, it yields a new ``Q`` object. For example the statement:: + + Q(question__startswith='Who') | Q(question__startswith='What') + +... yields a single ``Q`` object that represents the "OR" of two +"question__startswith" queries, equivalent to the SQL WHERE clause:: + + ... WHERE question LIKE 'Who%' OR question LIKE 'What%' + +You can compose statements of arbitrary complexity by combining ``Q`` objects +with the ``&`` and ``|`` operators. Parenthetical grouping can also be used. + +One or more ``Q`` objects can then provided as arguments to the lookup +functions. If multiple ``Q`` object arguments are provided to a lookup +function, they will be "AND"ed together. For example:: + + Poll.objects.get( + Q(question__startswith='Who'), + Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) ) -Each of the resulting ``Poll`` objects will have an extra attribute, ``choice_count``, -an integer count of associated ``Choice`` objects. Note that the parenthesis required by -most database engines around sub-selects are not required in Django's ``select`` -clauses. +... roughly translates into the SQL:: -``where`` / ``tables`` ----------------------- + SELECT * from polls WHERE question LIKE 'Who%' + 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 +arguments. All arguments provided to a lookup function (be they keyword +argument or ``Q`` object) are "AND"ed together. However, if a ``Q`` object is +provided, it must precede the definition of any keyword arguments. For +example:: + + Poll.objects.get( + Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), + question__startswith='Who') + +... would be a valid query, equivalent to the previous example; but:: + + # INVALID QUERY + Poll.objects.get( + question__startswith='Who', + Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))) + +... 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. + +.. _OR lookups examples page: http://www.djangoproject.com/documentation/models/or_lookups/ + + +Relationships (joins) +===================== + +When you define a relationship in a model (i.e., a ForeignKey, +OneToOneField, or ManyToManyField), Django uses the name of the +relationship to add a descriptor_ on every instance of the model. +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 + +Django also adds a descriptor for the 'other' side of 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, +Django will automatically derive a name for this descriptor. The name that +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. -If you need to explicitly pass extra ``WHERE`` clauses -- perhaps to perform -non-explicit joins -- use the ``where`` keyword. If you need to -join other tables into your query, you can pass their names to ``tables``. +There are two types of descriptor that can be employed: Single Object +Descriptors and Object Set Descriptors. The following table describes +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. -``where`` and ``tables`` both take a list of strings. All ``where`` parameters -are "AND"ed to any other search criteria. + =============== ============= ============= + Relation Type Local Model Related Model + =============== ============= ============= + OneToOneField Single Object Single Object + ForeignKey Single Object Object Set + + ManyToManyField Object Set Object Set + =============== ============= ============= + +Single object descriptor +------------------------ + +If the related object is a single object, the descriptor acts +just as if the related object were an attribute:: + + # Obtain the existing poll + old_poll = mychoice.poll + # Set a new poll + mychoice.poll = new_poll + # Save the change + mychoice.save() + +Whenever a change is made to a Single Object Descriptor, save() +must be called to commit the change to the database. + +If no `related_name` parameter is defined, Django will use the +lower case version of the source model name as the name for the +related descriptor. For example, if the ``Choice`` model had +a field:: + + coordinator = models.OneToOneField(User) + +... instances of the model ``User`` would be able to call: + + old_choice = myuser.choice + myuser.choice = new_choice + +By default, relations do not allow values of None; if you attempt +to assign None to a Single Object Descriptor, an AttributeError +will be thrown. However, if the relation has 'null=True' set +(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 +a descriptor on an instance is accessed, the database will be +queried, and the result stored. Subsequent attempts to access +the descriptor on the same instance will use the cached value. + +Object set descriptor +--------------------- + +An Object Set Descriptor acts just like the Manager - as an initial Query +Set describing the set of objects related to an instance. As such, any +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 +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 +related object set: + +``add(obj1, obj2, ...)`` + Add the specified objects to the related object set. + +``create(\**kwargs)`` + Create a new object, and put it in the related object set. See + _`Creating new objects` + +The Object Set Descriptor may also have utility methods to remove objects +from the related object set: + +``remove(obj1, obj2, ...)`` + Remove the specified objects from the related object set. + +``clear()`` + Remove all objects from the related object set. + +These two removal methods will not exist on ForeignKeys where ``Null=False`` +(such as in the Poll example). This is to prevent database inconsistency - if +the related field cannot be set to None, then an object cannot be removed +from one relation without adding it to another. + +The members of a related object set can be assigned from any iterable object. For example:: - polls.get_list(question__startswith='Who', where=['id IN (3, 4, 5, 20)']) + mypoll.choice_set = [choice1, choice2] -...translates (roughly) into the following SQL: +If the ``clear()`` method is available, any pre-existing objects will be removed +from the Object Set before all objects in the iterable (in this case, a list) +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. - SELECT * FROM polls_polls WHERE question LIKE 'Who%' AND id IN (3, 4, 5, 20); +Each of these operations on the Object Set Descriptor has immediate effect +on the database - every add, create and remove is immediately and +automatically saved to the database. -Changing objects -================ +Relationships and queries +========================= -Once you've retrieved an object from the database using any of the above -options, changing it is extremely easy. Make changes directly to the -objects fields, then call the object's ``save()`` method:: +When composing a ``filter`` or ``exclude`` refinement, it may be necessary to +include conditions that span relationships. Relations can be followed as deep +as required - just add descriptor names, separated by double underscores, to +describe the full path to the query attribute. The query:: - >>> p = polls.get_object(id__exact=15) - >>> p.slug = "new_slug" - >>> p.pub_date = datetime.datetime.now() - >>> p.save() + Foo.objects.filter(name1__name2__name3__attribute__lookup=value) -Creating new objects -==================== +... is interpreted as 'get every Foo that has a name1 that has a name2 that +has a name3 that has an attribute with lookup matching value'. In the Poll +example:: -Creating new objects (i.e. ``INSERT``) is done by creating new instances -of objects then calling save() on them:: + Choice.objects.filter(poll__slug__startswith="eggs") - >>> p = polls.Poll(slug="eggs", - ... question="How do you like your eggs?", - ... pub_date=datetime.datetime.now(), - ... expire_date=some_future_date) - >>> p.save() +... describes the set of choices for which the related poll has a slug +attribute that starts with "eggs". Django automatically composes the joins +and conditions required for the SQL query. -Calling ``save()`` on an object with a primary key whose value is ``None`` -signifies to Django that the object is new and should be inserted. +Creating new related objects +============================ -Related objects (e.g. ``Choices``) are created using convenience functions:: +Related objects are created using the ``create()`` convenience function on +the descriptor Manager for relation:: - >>> p.add_choice(choice="Over easy", votes=0) - >>> p.add_choice(choice="Scrambled", votes=0) - >>> p.add_choice(choice="Fertilized", votes=0) - >>> p.add_choice(choice="Poached", votes=0) - >>> p.get_choice_count() + >>> p.choice_set.create(choice="Over easy", votes=0) + >>> p.choice_set.create(choice="Scrambled", votes=0) + >>> p.choice_set.create(choice="Fertilized", votes=0) + >>> p.choice_set.create(choice="Poached", votes=0) + >>> p.choice_set.count() 4 -Each of those ``add_choice`` methods is equivalent to (but much simpler than):: +Each of those ``create()`` methods is equivalent to (but much simpler than):: - >>> c = polls.Choice(poll_id=p.id, choice="Over easy", votes=0) + >>> c = Choice(poll_id=p.id, choice="Over easy", votes=0) >>> c.save() -Note that when using the `add_foo()`` methods, you do not give any value +Note that when using the `create()`` method, you do not give any value for the ``id`` field, nor do you give a value for the field that stores the relation (``poll_id`` in this case). -The ``add_FOO()`` method always returns the newly created object. +The ``create()`` method always returns the newly created object. Deleting objects ================ @@ -514,31 +1371,27 @@ deletes the object and has no return value. Example:: >>> c.delete() -Comparing objects -================= +Objects can also be deleted in bulk. Every Query Set has a ``delete()`` method +that will delete all members of the query set. For example:: -To compare two model objects, just use the standard Python comparison operator, -the double equals sign: ``==``. Behind the scenes, that compares the primary -key values of two models. + >>> Polls.objects.filter(pub_date__year=2005).delete() -Using the ``Poll`` example above, the following two statements are equivalent:: +would bulk delete all Polls with a year of 2005. Note that ``delete()`` is the +only Query Set method that is not exposed on the Manager itself. - some_poll == other_poll - some_poll.id == other_poll.id +This is a safety mechanism to prevent you from accidentally requesting +``Polls.objects.delete()``, and deleting *all* the polls. -If a model's primary key isn't called ID, no problem. Comparisons will always -use the primary key, whatever it's called. For example, if a model's primary -key field is called ``name``, these two statements are equivalent:: +If you *actually* want to delete all the objects, then you have to explicitly +request a complete query set:: - some_obj == other_obj - some_obj.name == other_obj.name + Polls.objects.all().delete() Extra instance methods ====================== -In addition to ``save()``, ``delete()`` and all of the ``add_*`` and ``get_*`` -related-object methods, a model object might get any or all of the following -methods: +In addition to ``save()``, ``delete()``, a model object might get any or all +of the following methods: get_FOO_display() ----------------- @@ -572,10 +1425,10 @@ For every ``DateField`` and ``DateTimeField`` that does not have ``null=True``, the object will have ``get_next_by_FOO()`` and ``get_previous_by_FOO()`` methods, where ``FOO`` is the name of the field. This returns the next and previous object with respect to the date field, raising the appropriate -``*DoesNotExist`` exception when appropriate. +``DoesNotExist`` exception when appropriate. Both methods accept optional keyword arguments, which should be in the format -described in "Field lookups" above. +described in _`Field lookups` above. Note that in the case of identical date values, these methods will use the ID as a fallback check. This guarantees that no records are skipped or duplicated. @@ -604,14 +1457,14 @@ returns an empty string. get_FOO_size() -------------- -For every ``FileField``, the object will have a ``get_FOO_size()`` method, +For every ``FileField``, the object will have a ``get_FOO_filename()`` method, where ``FOO`` is the name of the field. This returns the size of the file, in bytes. (Behind the scenes, it uses ``os.path.getsize``.) save_FOO_file(filename, raw_contents) ------------------------------------- -For every ``FileField``, the object will have a ``save_FOO_file()`` method, +For every ``FileField``, the object will have a ``get_FOO_filename()`` method, where ``FOO`` is the name of the field. This saves the given file to the filesystem, using the given filename. If a file with the given filename already exists, Django adds an underscore to the end of the filename (but before the @@ -623,48 +1476,3 @@ get_FOO_height() and get_FOO_width() For every ``ImageField``, the object will have ``get_FOO_height()`` and ``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This returns the height (or width) of the image, as an integer, in pixels. - -Extra module functions -====================== - -In addition to every function described in "Basic lookup functions" above, a -model module might get any or all of the following methods: - -get_FOO_list(kind, \**kwargs) ------------------------------ - -For every ``DateField`` and ``DateTimeField``, the model module will have a -``get_FOO_list()`` function, where ``FOO`` is the name of the field. This -returns a list of ``datetime.datetime`` objects representing all available -dates of the given scope, as defined by the ``kind`` argument. ``kind`` should -be either ``"year"``, ``"month"`` or ``"day"``. Each ``datetime.datetime`` -object in the result list is "truncated" to the given ``type``. - - * ``"year"`` returns a list of all distinct year 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. - -Additional, optional keyword arguments, in the format described in -"Field lookups" above, are also accepted. - -Here's an example, using the ``Poll`` model defined above:: - - >>> from datetime import datetime - >>> p1 = polls.Poll(slug='whatsup', question="What's up?", - ... pub_date=datetime(2005, 2, 20), expire_date=datetime(2005, 3, 20)) - >>> p1.save() - >>> p2 = polls.Poll(slug='name', question="What's your name?", - ... pub_date=datetime(2005, 3, 20), expire_date=datetime(2005, 4, 20)) - >>> p2.save() - >>> polls.get_pub_date_list('year') - [datetime.datetime(2005, 1, 1)] - >>> polls.get_pub_date_list('month') - [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)] - >>> polls.get_pub_date_list('day') - [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)] - >>> polls.get_pub_date_list('day', question__contains='name') - [datetime.datetime(2005, 3, 20)] - -``get_FOO_list()`` also accepts an optional keyword argument ``order``, which -should be either ``"ASC"`` or ``"DESC"``. This specifies how to order the -results. Default is ``"ASC"``. |
