1
0
mirror of https://github.com/django/django.git synced 2025-10-24 14:16:09 +00:00

Fixed #34871, #36518 -- Implemented unresolved lookups expression replacement.

This allows the proper resolving of lookups when performing constraint
validation involving Q and Case objects.

Thanks Andrew Roberts for the report and Sarah for the tests and review.
This commit is contained in:
Simon Charette
2025-02-19 03:04:16 -05:00
committed by Sarah Boyce
parent 500bd42b96
commit 079d31e698
4 changed files with 124 additions and 4 deletions

View File

@@ -1,3 +1,5 @@
from datetime import datetime
from django.core.exceptions import FieldError
from django.db import connection
from django.db.models import (
@@ -10,8 +12,13 @@ from django.db.models import (
Value,
)
from django.db.models.expressions import NegatedExpression, RawSQL
from django.db.models.functions import Lower
from django.db.models.lookups import Exact, IsNull
from django.db.models.functions import ExtractDay, Lower, TruncDate
from django.db.models.lookups import (
Exact,
IntegerFieldExact,
IntegerLessThanOrEqual,
IsNull,
)
from django.db.models.sql.where import NothingNode
from django.test import SimpleTestCase, TestCase
@@ -292,6 +299,59 @@ class QTests(SimpleTestCase):
expected_base_fields,
)
def test_replace_expressions(self):
replacements = {F("timestamp"): Value(None)}
self.assertEqual(
Q(timestamp__date__day=25).replace_expressions(replacements),
Q(timestamp__date__day=25),
)
replacements = {F("timestamp"): Value(datetime(2025, 10, 23))}
self.assertEqual(
Q(timestamp__date__day=13).replace_expressions(replacements),
Q(
IntegerFieldExact(
ExtractDay(TruncDate(Value(datetime(2025, 10, 23)))),
13,
)
),
)
self.assertEqual(
Q(timestamp__date__day__lte=25).replace_expressions(replacements),
Q(
IntegerLessThanOrEqual(
ExtractDay(TruncDate(Value(datetime(2025, 10, 23)))),
25,
)
),
)
self.assertEqual(
(
Q(Q(timestamp__date__day__lte=25), timestamp__date__day=13)
).replace_expressions(replacements),
(
Q(
Q(
IntegerLessThanOrEqual(
ExtractDay(TruncDate(Value(datetime(2025, 10, 23)))),
25,
)
),
IntegerFieldExact(
ExtractDay(TruncDate(Value(datetime(2025, 10, 23)))),
13,
),
)
),
)
self.assertEqual(
Q(timestamp=None).replace_expressions(replacements),
Q(IsNull(Value(datetime(2025, 10, 23)), True)),
)
self.assertEqual(
Q(timestamp__date__day__invalid=25).replace_expressions(replacements),
Q(timestamp__date__day__invalid=25),
)
class QCheckTests(TestCase):
def test_basic(self):