[4.0.x] Fixed #33705 -- Fixed crash when using IsNull() lookup in filters.

Thanks Florian Apolloner for the report.
Thanks Simon Charette for the review.

Backport of 9f55489529 from main
This commit is contained in:
David Wobrock 2022-05-17 11:32:30 +02:00 committed by Mariusz Felisiak
parent de9c08c0f3
commit 4a86883e0a
3 changed files with 19 additions and 4 deletions

View File

@ -171,9 +171,10 @@ class Lookup(Expression):
c.lhs = self.lhs.resolve_expression(
query, allow_joins, reuse, summarize, for_save
)
c.rhs = self.rhs.resolve_expression(
query, allow_joins, reuse, summarize, for_save
)
if hasattr(self.rhs, "resolve_expression"):
c.rhs = self.rhs.resolve_expression(
query, allow_joins, reuse, summarize, for_save
)
return c
def select_format(self, compiler, sql, params):

View File

@ -11,3 +11,6 @@ Bugfixes
* Fixed a bug in Django 4.0 where not all :setting:`OPTIONS <CACHES-OPTIONS>`
were passed to a Redis client (:ticket:`33681`).
* Fixed a bug in Django 4.0 that caused a crash of ``QuerySet.filter()`` on
``IsNull()`` expressions (:ticket:`33705`).

View File

@ -23,6 +23,7 @@ from django.db.models.lookups import (
Exact,
GreaterThan,
GreaterThanOrEqual,
IsNull,
LessThan,
LessThanOrEqual,
)
@ -1243,7 +1244,7 @@ class LookupQueryingTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.s1 = Season.objects.create(year=1942, gt=1942)
cls.s2 = Season.objects.create(year=1842, gt=1942)
cls.s2 = Season.objects.create(year=1842, gt=1942, nulled_text_field="text")
cls.s3 = Season.objects.create(year=2042, gt=1942)
def test_annotate(self):
@ -1325,6 +1326,16 @@ class LookupQueryingTests(TestCase):
qs = Season.objects.filter(GreaterThan(F("year"), 1910))
self.assertCountEqual(qs, [self.s1, self.s3])
def test_isnull_lookup_in_filter(self):
self.assertSequenceEqual(
Season.objects.filter(IsNull(F("nulled_text_field"), False)),
[self.s2],
)
self.assertCountEqual(
Season.objects.filter(IsNull(F("nulled_text_field"), True)),
[self.s1, self.s3],
)
def test_filter_lookup_lhs(self):
qs = Season.objects.annotate(before_20=LessThan(F("year"), 2000)).filter(
before_20=LessThan(F("year"), 1900),