Revived a bunch of missing documentation that got lost in the docs-refactor.

This describes values_list(), the new cross-model order_by() syntax and the
effects of distinct(), values() and order_by() on each other.

Fixed #8634.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8694 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-08-29 05:04:26 +00:00
parent e66b0ae576
commit 2dba41056f
1 changed files with 119 additions and 6 deletions

View File

@ -145,10 +145,45 @@ like so::
Note: ``order_by('?')`` queries may be expensive and slow, depending on the
database backend you're using.
To order by a field in a different table, add the other table's name and a dot,
like so::
To order by a field in a different model, use the same syntax as when you are
querying across model relations. That is, the name of the field, followed by a
double underscore (``__``), followed by the name of the field in the new model,
and so on for as many models as you want to join. For example::
Entry.objects.order_by('blogs_blog.name', 'headline')
Entry.objects.order_by('blog__name', 'headline')
If you try to order by a field that is a relation to another model, Django will
use the default ordering on the related model (or order by the related model's
primary key if there is no ``Meta.ordering`` specified. For example::
Entry.objects.order_by('blog')
...is identical to::
Entry.objects.order_by('blog__id')
...since the ``Blog`` model has no default ordering specified.
Be cautious when ordering by fields in related models if you are also using
``distinct()``. See the note in the `distinct()`_ section for an explanation
of how related model ordering can change the expected results.
It is permissible to specify a multi-valued field to order the results by (for
example, a ``ManyToMany`` field). Normally this won't be a sensible thing to
do and it's really an advanced usage feature. However, if you know that your
queryset's filtering or available data implies that there will only be one
ordering piece of data for each of the main items you are selecting, the
ordering may well be exactly what you want to do. Use ordering on multi-valued
fields with care and make sure the results are what you expect.
**New in Django development version:** If you don't want any ordering to be
applied to a query, not even the default ordering, call ``order_by()`` with no
parameters.
**New in Django development version:** The syntax for ordering across related
models has changed. See the `Django 0.96 documentation`_ for the old behaviour.
.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield
There's no way to specify whether ordering should be case sensitive. With
respect to case-sensitivity, Django will order results however your database
@ -171,10 +206,29 @@ eliminates duplicate rows from the query results.
By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this
is rarely a problem, because simple queries such as ``Blog.objects.all()``
don't introduce the possibility of duplicate result rows.
don't introduce the possibility of duplicate result rows. However, if your
query spans multiple tables, it's possible to get duplicate results when a
``QuerySet`` is evaluated. That's when you'd use ``distinct()``.
.. note::
Any fields used in an `order_by(*fields)`_ call are included in the SQL
``SELECT`` columns. This can sometimes lead to unexpected results when
used in conjunction with ``distinct()``. If you order by fields from a
related model, those fields will be added to the selected columns and they
may make otherwise duplicate rows appear to be distinct. Since the extra
columns don't appear in the returned results (they are only there to
support ordering), it sometimes looks like non-distinct results are being
returned.
Similarly, if you use a ``values()`` query to restrict the columns
selected, the columns used in any ``order_by()`` (or default model
ordering) will still be involved and may affect uniqueness of the results.
The moral here is that if you are using ``distinct()`` be careful about
ordering by related models. Similarly, when using ``distinct()`` and
``values()`` together, be careful when ordering by fields not in the
``values()`` call.
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)``
~~~~~~~~~~~~~~~~~~~
@ -209,6 +263,37 @@ Example::
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]
A couple of subtleties that are worth mentioning:
* The ``values()`` method does not return anything for
:class:`~django.db.models.ManyToManyField` attributes and will raise an
error if you try to pass in this type of field to it.
* If you have a field called ``foo`` that is a
:class:`~django.db.models.ForeignKey`, the default ``values()`` call
will return a dictionary key called ``foo_id``, since this is the name
of the hidden model attribute that stores the actual value (the ``foo``
attribute refers to the related model). When you are calling
``values()`` and passing in field names, you can pass in either ``foo``
or ``foo_id`` and you will get back the same thing (the dictionary key
will match the field name you passed in).
For example::
>>> Entry.objects.values()
[{'blog_id: 1, 'headline': u'First Entry', ...}, ...]
>>> Entry.objects.values('blog')
[{'blog': 1}, ...]
>>> Entry.objects.values('blog_id')
[{'blog_id': 1}, ...]
* When using ``values()`` together with ``distinct()``, be aware that
ordering can affect the results. See the note in the `distinct()`_
section, above, for details.
**New in Django development version:** Previously, it was not possible to pass
``blog_id`` to ``values()`` in the above example, only ``blog``.
A ``ValuesQuerySet`` is useful when you know you're only going to need values
from a small number of the available fields and you won't need the
functionality of a model instance object. It's more efficient to select only
@ -226,6 +311,34 @@ followed (optionally) by any output-affecting methods (such as ``values()``),
but it doesn't really matter. This is your chance to really flaunt your
individualism.
``values_list(*fields)``
~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
This is similar to ``values()`` except that instead of returning a list of
dictionaries, it returns a list of tuples. Each tuple contains the value from
the respective field passed into the ``values_list()`` call -- so the first
item is the first field, etc. For example::
>>> Entry.objects.values_list('id', 'headline')
[(1, u'First entry'), ...]
If you only pass in a single field, you can also pass in the ``flat``
parameter. If ``True``, this will mean the returned results are single values,
rather than one-tuples. An example should make the difference clearer::
>>> Entry.objects.values_list('id').order_by('id')
[(1,), (2,), (3,), ...]
>>> Entry.objects.values_list('id', flat=True).order_by('id')
[1, 2, 3, ...]
It is an error to pass in ``flat`` when there is more than one field.
If you don't pass any values to ``values_list()``, it will return all the
fields in the model, in the order they were declared.
``dates(field, kind, order='ASC')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~