mirror of
https://github.com/django/django.git
synced 2025-08-03 10:34:04 +00:00
Fixed #27021 -- Allowed lookup expressions in annotations, aggregations, and QuerySet.filter().
Thanks Hannes Ljungberg and Simon Charette for reviews. Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
f5dccbafb9
commit
f42ccdd835
11 changed files with 268 additions and 48 deletions
|
@ -48,6 +48,10 @@ objects that have an ``output_field`` that is a
|
|||
:class:`~django.db.models.BooleanField`. The result is provided using the
|
||||
``then`` keyword.
|
||||
|
||||
.. versionchanged:: 4.0
|
||||
|
||||
Support for lookup expressions was added.
|
||||
|
||||
Some examples::
|
||||
|
||||
>>> from django.db.models import F, Q, When
|
||||
|
@ -68,6 +72,13 @@ Some examples::
|
|||
... account_type=OuterRef('account_type'),
|
||||
... ).exclude(pk=OuterRef('pk')).values('pk')
|
||||
>>> When(Exists(non_unique_account_type), then=Value('non unique'))
|
||||
>>> # Condition can be created using lookup expressions.
|
||||
>>> from django.db.models.lookups import GreaterThan, LessThan
|
||||
>>> When(
|
||||
... GreaterThan(F('registered_on'), date(2014, 1, 1)) &
|
||||
... LessThan(F('registered_on'), date(2015, 1, 1)),
|
||||
... then='account_type',
|
||||
... )
|
||||
|
||||
Keep in mind that each of these values can be an expression.
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ Some examples
|
|||
|
||||
from django.db.models import Count, F, Value
|
||||
from django.db.models.functions import Length, Upper
|
||||
from django.db.models.lookups import GreaterThan
|
||||
|
||||
# Find companies that have more employees than chairs.
|
||||
Company.objects.filter(num_employees__gt=F('num_chairs'))
|
||||
|
@ -76,6 +77,13 @@ Some examples
|
|||
Exists(Employee.objects.filter(company=OuterRef('pk'), salary__gt=10))
|
||||
)
|
||||
|
||||
# Lookup expressions can also be used directly in filters
|
||||
Company.objects.filter(GreaterThan(F('num_employees'), F('num_chairs')))
|
||||
# or annotations.
|
||||
Company.objects.annotate(
|
||||
need_chairs=GreaterThan(F('num_employees'), F('num_chairs')),
|
||||
)
|
||||
|
||||
Built-in Expressions
|
||||
====================
|
||||
|
||||
|
|
|
@ -177,16 +177,21 @@ following methods:
|
|||
comparison between ``lhs`` and ``rhs`` such as ``lhs in rhs`` or
|
||||
``lhs > rhs``.
|
||||
|
||||
The notation to use a lookup in an expression is
|
||||
``<lhs>__<lookup_name>=<rhs>``.
|
||||
The primary notation to use a lookup in an expression is
|
||||
``<lhs>__<lookup_name>=<rhs>``. Lookups can also be used directly in
|
||||
``QuerySet`` filters::
|
||||
|
||||
This class acts as a query expression, but, since it has ``=<rhs>`` on its
|
||||
construction, lookups must always be the end of a lookup expression.
|
||||
Book.objects.filter(LessThan(F('word_count'), 7500))
|
||||
|
||||
…or annotations::
|
||||
|
||||
Book.objects.annotate(is_short_story=LessThan(F('word_count'), 7500))
|
||||
|
||||
.. attribute:: lhs
|
||||
|
||||
The left-hand side - what is being looked up. The object must follow
|
||||
the :ref:`Query Expression API <query-expression>`.
|
||||
The left-hand side - what is being looked up. The object typically
|
||||
follows the :ref:`Query Expression API <query-expression>`. It may also
|
||||
be a plain value.
|
||||
|
||||
.. attribute:: rhs
|
||||
|
||||
|
@ -213,3 +218,8 @@ following methods:
|
|||
.. method:: process_rhs(compiler, connection)
|
||||
|
||||
Behaves the same way as :meth:`process_lhs`, for the right-hand side.
|
||||
|
||||
.. versionchanged:: 4.0
|
||||
|
||||
Support for using lookups in ``QuerySet`` annotations, aggregations,
|
||||
and directly in filters was added.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue