[1.8.x] Fixed #24705 -- Fixed negated Q objects in expressions.

Avoided split_exclude() for Q when used as an expression.

Backport of bc87061a3c from master
This commit is contained in:
Anssi Kääriäinen 2015-05-19 14:49:00 +03:00 committed by Tim Graham
parent 63d60dfe29
commit db65660928
4 changed files with 54 additions and 6 deletions

View file

@ -1063,6 +1063,48 @@ class CaseExpressionTests(TestCase):
lambda x: (x, x.foo)
)
def test_m2m_exclude(self):
CaseTestModel.objects.create(integer=10, integer2=1, string='1')
qs = CaseTestModel.objects.values_list('id', 'integer').annotate(
cnt=models.Sum(
Case(When(~Q(fk_rel__integer=1), then=1), default=2),
output_field=models.IntegerField()
),
).order_by('integer')
# The first o has 2 as its fk_rel__integer=1, thus it hits the
# default=2 case. The other ones have 2 as the result as they have 2
# fk_rel objects, except for integer=4 and integer=10 (created above).
# The integer=4 case has one integer, thus the result is 1, and
# integer=10 doesn't have any and this too generates 1 (instead of 0)
# as ~Q() also matches nulls.
self.assertQuerysetEqual(
qs,
[(1, 2), (2, 2), (2, 2), (3, 2), (3, 2), (3, 2), (4, 1), (10, 1)],
lambda x: x[1:]
)
def test_m2m_reuse(self):
CaseTestModel.objects.create(integer=10, integer2=1, string='1')
# Need to use values before annotate so that Oracle will not group
# by fields it isn't capable of grouping by.
qs = CaseTestModel.objects.values_list('id', 'integer').annotate(
cnt=models.Sum(
Case(When(~Q(fk_rel__integer=1), then=1), default=2),
output_field=models.IntegerField()
),
).annotate(
cnt2=models.Sum(
Case(When(~Q(fk_rel__integer=1), then=1), default=2),
output_field=models.IntegerField()
),
).order_by('integer')
self.assertEqual(str(qs.query).count(' JOIN '), 1)
self.assertQuerysetEqual(
qs,
[(1, 2, 2), (2, 2, 2), (2, 2, 2), (3, 2, 2), (3, 2, 2), (3, 2, 2), (4, 1, 1), (10, 1, 1)],
lambda x: x[1:]
)
class CaseDocumentationExamples(TestCase):
@classmethod