diff options
| author | Matthew Wilkes <git@matthewwilkes.name> | 2017-06-18 16:53:40 +0100 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2018-02-10 19:08:55 -0500 |
| commit | 2162f0983de0dfe2178531638ce7ea56f54dd4e7 (patch) | |
| tree | bb1e859159200fa7ebeeaa02ec3908e1cf5d2655 /docs | |
| parent | bf26f66029bca94b007a2452679ac004598364a6 (diff) | |
Fixed #24747 -- Allowed transforms in QuerySet.order_by() and distinct(*fields).
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/howto/custom-lookups.txt | 15 | ||||
| -rw-r--r-- | docs/ref/models/expressions.txt | 8 | ||||
| -rw-r--r-- | docs/ref/models/querysets.txt | 32 | ||||
| -rw-r--r-- | docs/releases/2.1.txt | 6 |
4 files changed, 59 insertions, 2 deletions
diff --git a/docs/howto/custom-lookups.txt b/docs/howto/custom-lookups.txt index 32037a29aa..55fdc42237 100644 --- a/docs/howto/custom-lookups.txt +++ b/docs/howto/custom-lookups.txt @@ -138,6 +138,21 @@ SQL:: Note that in case there is no other lookup specified, Django interprets ``change__abs=27`` as ``change__abs__exact=27``. +This also allows the result to be used in ``ORDER BY`` and ``DISTINCT ON`` +clauses. For example ``Experiment.objects.order_by('change__abs')`` generates:: + + SELECT ... ORDER BY ABS("experiments"."change") ASC + +And on databases that support distinct on fields (such as PostgreSQL), +``Experiment.objects.distinct('change__abs')`` generates:: + + SELECT ... DISTINCT ON ABS("experiments"."change") + +.. versionchanged:: 2.1 + + Ordering and distinct support as described in the last two paragraphs was + added. + When looking for which lookups are allowable after the ``Transform`` has been applied, Django uses the ``output_field`` attribute. We didn't need to specify this here as it didn't change, but supposing we were applying ``AbsoluteValue`` diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt index 8ca975cc3a..70e3a58616 100644 --- a/docs/ref/models/expressions.txt +++ b/docs/ref/models/expressions.txt @@ -64,10 +64,14 @@ Some examples # Aggregates can contain complex computations also Company.objects.annotate(num_offerings=Count(F('products') + F('services'))) - # Expressions can also be used in order_by() + # Expressions can also be used in order_by(), either directly Company.objects.order_by(Length('name').asc()) Company.objects.order_by(Length('name').desc()) - + # or using the double underscore lookup syntax. + from django.db.models import CharField + from django.db.models.functions import Length + CharField.register_lookup(Length) + Company.objects.order_by('name__length') Built-in Expressions ==================== diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index be07f0821d..2d6702beeb 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -535,6 +535,19 @@ The ``values()`` method also takes optional keyword arguments, >>> Blog.objects.values(lower_name=Lower('name')) <QuerySet [{'lower_name': 'beatles blog'}]> +You can use built-in and :doc:`custom lookups </howto/custom-lookups>` in +ordering. For example:: + + >>> from django.db.models import CharField + >>> from django.db.models.functions import Lower + >>> CharField.register_lookup(Lower, 'lower') + >>> Blog.objects.values('name__lower') + <QuerySet [{'name__lower': 'beatles blog'}]> + +.. versionchanged:: 2.1 + + Support for lookups was added. + An aggregate within a ``values()`` clause is applied before other arguments within the same ``values()`` clause. If you need to group by another value, add it to an earlier ``values()`` clause instead. For example:: @@ -580,6 +593,25 @@ A few subtleties that are worth mentioning: * Calling :meth:`only()` and :meth:`defer()` after ``values()`` doesn't make sense, so doing so will raise a ``NotImplementedError``. +* Combining transforms and aggregates requires the use of two :meth:`annotate` + calls, either explicitly or as keyword arguments to :meth:`values`. As above, + if the transform has been registered on the relevant field type the first + :meth:`annotate` can be omitted, thus the following examples are equivalent:: + + >>> from django.db.models import CharField, Count + >>> from django.db.models.functions import Lower + >>> CharField.register_lookup(Lower, 'lower') + >>> Blog.objects.values('entry__authors__name__lower').annotate(entries=Count('entry')) + <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> + >>> Blog.objects.values( + ... entry__authors__name__lower=Lower('entry__authors__name') + ... ).annotate(entries=Count('entry')) + <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> + >>> Blog.objects.annotate( + ... entry__authors__name__lower=Lower('entry__authors__name') + ... ).values('entry__authors__name__lower').annotate(entries=Count('entry')) + <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> + It 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. diff --git a/docs/releases/2.1.txt b/docs/releases/2.1.txt index ae3dd67bc9..31252432bb 100644 --- a/docs/releases/2.1.txt +++ b/docs/releases/2.1.txt @@ -187,6 +187,9 @@ Models * Query expressions can now be negated using a minus sign. +* :meth:`.QuerySet.order_by` and :meth:`distinct(*fields) <.QuerySet.distinct>` + now support using field transforms. + Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~ @@ -242,6 +245,9 @@ Database backend API * Renamed the ``allow_sliced_subqueries`` database feature flag to ``allow_sliced_subqueries_with_in``. +* ``DatabaseOperations.distinct_sql()`` now requires an additional ``params`` + argument and returns a tuple of SQL and parameters instead of a SQL string. + :mod:`django.contrib.gis` ------------------------- |
