Skip to content

Commit 587b179

Browse files
rheardfelixxm
authored andcommitted
Fixed #31606 -- Allowed using condition with lookups in When() expression.
1 parent 2aac176 commit 587b179

File tree

4 files changed

+26
-3
lines changed

4 files changed

+26
-3
lines changed

django/db/models/expressions.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,8 +876,11 @@ class When(Expression):
876876
conditional = False
877877

878878
def __init__(self, condition=None, then=None, **lookups):
879-
if lookups and condition is None:
880-
condition, lookups = Q(**lookups), None
879+
if lookups:
880+
if condition is None:
881+
condition, lookups = Q(**lookups), None
882+
elif getattr(condition, 'conditional', False):
883+
condition, lookups = Q(condition, **lookups), None
881884
if condition is None or not getattr(condition, 'conditional', False) or lookups:
882885
raise TypeError(
883886
'When() supports a Q object, a boolean expression, or lookups '

docs/ref/models/conditional-expressions.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ Keep in mind that each of these values can be an expression.
8181
>>> When(then__exact=0, then=1)
8282
>>> When(Q(then=0), then=1)
8383

84+
.. versionchanged:: 3.2
85+
86+
Support for using the ``condition`` argument with ``lookups`` was added.
87+
8488
``Case``
8589
--------
8690

docs/releases/3.2.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ Models
178178
supported on PostgreSQL, allows acquiring weaker locks that don't block the
179179
creation of rows that reference locked rows through a foreign key.
180180

181+
* :class:`When() <django.db.models.expressions.When>` expression now allows
182+
using the ``condition`` argument with ``lookups``.
183+
181184
Requests and Responses
182185
~~~~~~~~~~~~~~~~~~~~~~
183186

tests/expressions_case/tests.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from django.core.exceptions import FieldError
88
from django.db.models import (
9-
BinaryField, Case, CharField, Count, DurationField, F,
9+
BinaryField, BooleanField, Case, CharField, Count, DurationField, F,
1010
GenericIPAddressField, IntegerField, Max, Min, Q, Sum, TextField,
1111
TimeField, UUIDField, Value, When,
1212
)
@@ -312,6 +312,17 @@ def test_in_subquery(self):
312312
transform=attrgetter('integer', 'integer2')
313313
)
314314

315+
def test_condition_with_lookups(self):
316+
qs = CaseTestModel.objects.annotate(
317+
test=Case(
318+
When(Q(integer2=1), string='2', then=Value(False)),
319+
When(Q(integer2=1), string='1', then=Value(True)),
320+
default=Value(False),
321+
output_field=BooleanField(),
322+
),
323+
)
324+
self.assertIs(qs.get(integer=1).test, True)
325+
315326
def test_case_reuse(self):
316327
SOME_CASE = Case(
317328
When(pk=0, then=Value('0')),
@@ -1350,6 +1361,8 @@ def test_invalid_when_constructor_args(self):
13501361
When(condition=object())
13511362
with self.assertRaisesMessage(TypeError, msg):
13521363
When(condition=Value(1, output_field=IntegerField()))
1364+
with self.assertRaisesMessage(TypeError, msg):
1365+
When(Value(1, output_field=IntegerField()), string='1')
13531366
with self.assertRaisesMessage(TypeError, msg):
13541367
When()
13551368

0 commit comments

Comments
 (0)