|
@@ -715,6 +715,30 @@ class DynamicFilterLookupExpressionTestCase(TestCase):
|
|
|
params = {'slug__iregex': ['^DEF-[a-z]*-2$']}
|
|
params = {'slug__iregex': ['^DEF-[a-z]*-2$']}
|
|
|
self.assertEqual(SiteFilterSet(params, Site.objects.all()).qs.count(), 1)
|
|
self.assertEqual(SiteFilterSet(params, Site.objects.all()).qs.count(), 1)
|
|
|
|
|
|
|
|
|
|
+ def test_site_null_string_partial_lookups(self):
|
|
|
|
|
+ """
|
|
|
|
|
+ The null choice value must be treated as a literal string for lookups which cannot take None (#23632).
|
|
|
|
|
+ """
|
|
|
|
|
+ Site.objects.filter(name='Site 1').update(description='Null Site')
|
|
|
|
|
+ lookups = {
|
|
|
|
|
+ 'description__ic': 1,
|
|
|
|
|
+ 'description__nic': 2,
|
|
|
|
|
+ 'description__isw': 1,
|
|
|
|
|
+ 'description__nisw': 2,
|
|
|
|
|
+ 'description__iew': 0,
|
|
|
|
|
+ 'description__niew': 3,
|
|
|
|
|
+ 'description__regex': 0,
|
|
|
|
|
+ 'description__iregex': 1,
|
|
|
|
|
+ }
|
|
|
|
|
+ for lookup, count in lookups.items():
|
|
|
|
|
+ with self.subTest(lookup=lookup):
|
|
|
|
|
+ params = {lookup: ['null']}
|
|
|
|
|
+ self.assertEqual(SiteFilterSet(params, Site.objects.all()).qs.count(), count)
|
|
|
|
|
+
|
|
|
|
|
+ # Exact lookups still translate the null choice value to IS NULL
|
|
|
|
|
+ self.assertEqual(SiteFilterSet({'name': ['null']}, Site.objects.all()).qs.count(), 0)
|
|
|
|
|
+ self.assertEqual(SiteFilterSet({'name__n': ['null']}, Site.objects.all()).qs.count(), 3)
|
|
|
|
|
+
|
|
|
def test_provider_asn_lt(self):
|
|
def test_provider_asn_lt(self):
|
|
|
params = {'asn__lt': [65101]}
|
|
params = {'asn__lt': [65101]}
|
|
|
self.assertEqual(ASNFilterSet(params, ASN.objects.all()).qs.count(), 1)
|
|
self.assertEqual(ASNFilterSet(params, ASN.objects.all()).qs.count(), 1)
|