Fixed #33705 -- Fixed crash when using IsNull() lookup in filters.

Thanks Florian Apolloner for the report.
Thanks Simon Charette for the review.
This commit is contained in:
David Wobrock 2022-05-17 11:32:30 +02:00 committed by Mariusz Felisiak
parent 4525d689e9
commit 9f55489529
3 changed files with 19 additions and 4 deletions

View File

@ -171,9 +171,10 @@ class Lookup(Expression):
c.lhs = self.lhs.resolve_expression( c.lhs = self.lhs.resolve_expression(
query, allow_joins, reuse, summarize, for_save query, allow_joins, reuse, summarize, for_save
) )
c.rhs = self.rhs.resolve_expression( if hasattr(self.rhs, "resolve_expression"):
query, allow_joins, reuse, summarize, for_save c.rhs = self.rhs.resolve_expression(
) query, allow_joins, reuse, summarize, for_save
)
return c return c
def select_format(self, compiler, sql, params): 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>` * Fixed a bug in Django 4.0 where not all :setting:`OPTIONS <CACHES-OPTIONS>`
were passed to a Redis client (:ticket:`33681`). 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

@ -24,6 +24,7 @@ from django.db.models.lookups import (
Exact, Exact,
GreaterThan, GreaterThan,
GreaterThanOrEqual, GreaterThanOrEqual,
IsNull,
LessThan, LessThan,
LessThanOrEqual, LessThanOrEqual,
) )
@ -1284,7 +1285,7 @@ class LookupQueryingTests(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
cls.s1 = Season.objects.create(year=1942, gt=1942) 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) cls.s3 = Season.objects.create(year=2042, gt=1942)
def test_annotate(self): def test_annotate(self):
@ -1366,6 +1367,16 @@ class LookupQueryingTests(TestCase):
qs = Season.objects.filter(GreaterThan(F("year"), 1910)) qs = Season.objects.filter(GreaterThan(F("year"), 1910))
self.assertCountEqual(qs, [self.s1, self.s3]) 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): def test_filter_lookup_lhs(self):
qs = Season.objects.annotate(before_20=LessThan(F("year"), 2000)).filter( qs = Season.objects.annotate(before_20=LessThan(F("year"), 2000)).filter(
before_20=LessThan(F("year"), 1900), before_20=LessThan(F("year"), 1900),