mirror of
https://github.com/django/django.git
synced 2025-01-03 06:55:47 +00:00
Fixed #31667 -- Made __in lookup ignore None values.
This commit is contained in:
parent
36db4dd937
commit
5776a1660e
@ -366,10 +366,12 @@ class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.rhs_is_direct_value():
|
if self.rhs_is_direct_value():
|
||||||
|
# Remove None from the list as NULL is never equal to anything.
|
||||||
try:
|
try:
|
||||||
rhs = OrderedSet(self.rhs)
|
rhs = OrderedSet(self.rhs)
|
||||||
|
rhs.discard(None)
|
||||||
except TypeError: # Unhashable items in self.rhs
|
except TypeError: # Unhashable items in self.rhs
|
||||||
rhs = self.rhs
|
rhs = [r for r in self.rhs if r is not None]
|
||||||
|
|
||||||
if not rhs:
|
if not rhs:
|
||||||
raise EmptyResultSet
|
raise EmptyResultSet
|
||||||
|
@ -576,8 +576,6 @@ class LookupTests(TestCase):
|
|||||||
self.assertQuerysetEqual(Article.objects.none().iterator(), [])
|
self.assertQuerysetEqual(Article.objects.none().iterator(), [])
|
||||||
|
|
||||||
def test_in(self):
|
def test_in(self):
|
||||||
# using __in with an empty list should return an empty query set
|
|
||||||
self.assertQuerysetEqual(Article.objects.filter(id__in=[]), [])
|
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
Article.objects.exclude(id__in=[]),
|
Article.objects.exclude(id__in=[]),
|
||||||
[
|
[
|
||||||
@ -591,6 +589,9 @@ class LookupTests(TestCase):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_in_empty_list(self):
|
||||||
|
self.assertSequenceEqual(Article.objects.filter(id__in=[]), [])
|
||||||
|
|
||||||
def test_in_different_database(self):
|
def test_in_different_database(self):
|
||||||
with self.assertRaisesMessage(
|
with self.assertRaisesMessage(
|
||||||
ValueError,
|
ValueError,
|
||||||
@ -603,6 +604,31 @@ class LookupTests(TestCase):
|
|||||||
query = Article.objects.filter(slug__in=['a%d' % i for i in range(1, 8)]).values('pk').query
|
query = Article.objects.filter(slug__in=['a%d' % i for i in range(1, 8)]).values('pk').query
|
||||||
self.assertIn(' IN (a1, a2, a3, a4, a5, a6, a7) ', str(query))
|
self.assertIn(' IN (a1, a2, a3, a4, a5, a6, a7) ', str(query))
|
||||||
|
|
||||||
|
def test_in_ignore_none(self):
|
||||||
|
with self.assertNumQueries(1) as ctx:
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
Article.objects.filter(id__in=[None, self.a1.id]),
|
||||||
|
[self.a1],
|
||||||
|
)
|
||||||
|
sql = ctx.captured_queries[0]['sql']
|
||||||
|
self.assertIn('IN (%s)' % self.a1.pk, sql)
|
||||||
|
|
||||||
|
def test_in_ignore_solo_none(self):
|
||||||
|
with self.assertNumQueries(0):
|
||||||
|
self.assertSequenceEqual(Article.objects.filter(id__in=[None]), [])
|
||||||
|
|
||||||
|
def test_in_ignore_none_with_unhashable_items(self):
|
||||||
|
class UnhashableInt(int):
|
||||||
|
__hash__ = None
|
||||||
|
|
||||||
|
with self.assertNumQueries(1) as ctx:
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
Article.objects.filter(id__in=[None, UnhashableInt(self.a1.id)]),
|
||||||
|
[self.a1],
|
||||||
|
)
|
||||||
|
sql = ctx.captured_queries[0]['sql']
|
||||||
|
self.assertIn('IN (%s)' % self.a1.pk, sql)
|
||||||
|
|
||||||
def test_error_messages(self):
|
def test_error_messages(self):
|
||||||
# Programming errors are pointed out with nice error messages
|
# Programming errors are pointed out with nice error messages
|
||||||
with self.assertRaisesMessage(
|
with self.assertRaisesMessage(
|
||||||
|
Loading…
Reference in New Issue
Block a user