From 2162f0983de0dfe2178531638ce7ea56f54dd4e7 Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Sun, 18 Jun 2017 16:53:40 +0100 Subject: Fixed #24747 -- Allowed transforms in QuerySet.order_by() and distinct(*fields). --- docs/ref/models/expressions.txt | 8 ++++++-- docs/ref/models/querysets.txt | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'docs/ref') 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')) +You can use built-in and :doc:`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') + + +.. 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')) + + >>> Blog.objects.values( + ... entry__authors__name__lower=Lower('entry__authors__name') + ... ).annotate(entries=Count('entry')) + + >>> Blog.objects.annotate( + ... entry__authors__name__lower=Lower('entry__authors__name') + ... ).values('entry__authors__name__lower').annotate(entries=Count('entry')) + + 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. -- cgit v1.3