summaryrefslogtreecommitdiff
path: root/docs/ref
diff options
context:
space:
mode:
Diffstat (limited to 'docs/ref')
-rw-r--r--docs/ref/models/expressions.txt8
-rw-r--r--docs/ref/models/querysets.txt32
2 files changed, 38 insertions, 2 deletions
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.