Changes between Initial Version and Version 2 of Ticket #36787


Ignore:
Timestamp:
Dec 9, 2025, 3:12:36 PM (3 days ago)
Author:
Jacob Walls
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #36787 – Description

    initial v2  
     1The invariance between `__in` and `In` is broken when the right hand side contains a mix of expressions and strings (where the strings are possible literal values). EDIT: replaced draft test case, first version was misleading.
    12{{{#!diff
    23diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py
    3 index 5b9dd8e5ec..4cb90ed1d9 100644
     4index 5b9dd8e5ec..a34d95b8cb 100644
    45--- a/tests/lookup/tests.py
    56+++ b/tests/lookup/tests.py
    6 @@ -1847,6 +1847,8 @@ class LookupQueryingTests(TestCase):
    7              ((1842, 2042), (self.s2, self.s3)),
    8              ((1942, 1942, 1942), (self.s1,)),
    9              ((1942, 2042, 1842), (self.s1, self.s2, self.s3)),
    10 +            # Mix expressions and string field references.
    11 +            ((models.F("year") + 100, "gt"), (self.s1,)),
    12          ]
     7@@ -1855,6 +1855,19 @@ class LookupQueryingTests(TestCase):
     8                     Season.objects.filter(In(F("year"), years)).order_by("pk"), seasons
     9                 )
    1310 
    14          for years, seasons in test_cases:
    15 ).exists()
     11+    def test_in_lookup_in_filter_text_field(self):
     12+        self.assertSequenceEqual(
     13+            # this works...
     14+            # Season.objects.filter(
     15+            #     nulled_text_field__in=[F("nulled_text_field"), "special_value"]
     16+            # ),
     17+            # this doesn't...
     18+            Season.objects.filter(
     19+                In(F("nulled_text_field"), [F("nulled_text_field"), "special_value"])
     20+            ),
     21+            [self.s2],
     22+        )
     23+
     24     def test_filter_lookup_lhs(self):
     25         qs = Season.objects.annotate(before_20=LessThan(F("year"), 2000)).filter(
     26             before_20=LessThan(F("year"), 1900),
     27
    1628}}}
    1729{{{#!py
    1830======================================================================
    19 ERROR: test_in_lookup_in_filter (lookup.tests.LookupQueryingTests.test_in_lookup_in_filter) (years=(<CombinedExpression: F(year) + Value(100)>, 'gt'), seasons=(<Season: 1942>,))
     31ERROR: test_in_lookup_in_filter_text_field (lookup.tests.LookupQueryingTests.test_in_lookup_in_filter_text_field)
    2032----------------------------------------------------------------------
    2133Traceback (most recent call last):
    22   File "/Users/jwalls/django/tests/lookup/tests.py", line 1857, in test_in_lookup_in_filter
    23     Season.objects.filter(In(F("year"), years)).order_by("pk"), seasons
    24                           ~~^^^^^^^^^^^^^^^^^^
    25   File "/Users/jwalls/django/django/db/models/lookups.py", line 35, in __init__
     34  File "/django/source/tests/lookup/tests.py", line 1866, in test_in_lookup_in_filter_text_field
     35    In(F("nulled_text_field"), [F("nulled_text_field"), "special_value"])
     36  File "/django/source/django/db/models/lookups.py", line 35, in __init__
    2637    self.rhs = self.get_prep_lookup()
    27                ~~~~~~~~~~~~~~~~~~~~^^
    28   File "/Users/jwalls/django/django/db/models/lookups.py", line 517, in get_prep_lookup
     38               ^^^^^^^^^^^^^^^^^^^^^^
     39  File "/django/source/django/db/models/lookups.py", line 517, in get_prep_lookup
    2940    return super().get_prep_lookup()
    30            ~~~~~~~~~~~~~~~~~~~~~~~^^
    31   File "/Users/jwalls/django/django/db/models/lookups.py", line 310, in get_prep_lookup
     41           ^^^^^^^^^^^^^^^^^^^^^^^^^
     42  File "/django/source/django/db/models/lookups.py", line 310, in get_prep_lookup
    3243    Value(prep_value, self.lhs.output_field)
    3344                      ^^^^^^^^^^^^^^^^^^^^^
Back to Top