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:
parent
e66b0ae576
commit
2dba41056f
|
@ -145,10 +145,45 @@ like so::
|
||||||
Note: ``order_by('?')`` queries may be expensive and slow, depending on the
|
Note: ``order_by('?')`` queries may be expensive and slow, depending on the
|
||||||
database backend you're using.
|
database backend you're using.
|
||||||
|
|
||||||
To order by a field in a different table, add the other table's name and a dot,
|
To order by a field in a different model, use the same syntax as when you are
|
||||||
like so::
|
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
|
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
|
||||||
|
@ -171,10 +206,29 @@ eliminates duplicate rows from the query results.
|
||||||
|
|
||||||
By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this
|
By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this
|
||||||
is rarely a problem, because simple queries such as ``Blog.objects.all()``
|
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)``
|
``values(*fields)``
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -209,6 +263,37 @@ Example::
|
||||||
>>> Blog.objects.values('id', 'name')
|
>>> Blog.objects.values('id', 'name')
|
||||||
[{'id': 1, 'name': 'Beatles Blog'}]
|
[{'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
|
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
|
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
|
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
|
but it doesn't really matter. This is your chance to really flaunt your
|
||||||
individualism.
|
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')``
|
``dates(field, kind, order='ASC')``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue