From 94e22381079d65dccb9ac1ad9a9ebea2af2fdf66 Mon Sep 17 00:00:00 2001 From: jpribyl Date: Sun, 30 Aug 2020 11:13:37 -0600 Subject: [PATCH] Refs #31894 -- Added tests for JSONField key lookups with QuerySet.exclude(). --- tests/model_fields/test_jsonfield.py | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index 665e46e6a3..79f2609c35 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -275,7 +275,7 @@ class TestQuerying(TestCase): 'n': [None], }, [1, [2]], - {'k': True, 'l': False}, + {'k': True, 'l': False, 'foo': 'bax'}, { 'foo': 'bar', 'baz': {'a': 'b', 'c': 'd'}, @@ -616,6 +616,52 @@ class TestQuerying(TestCase): ) self.assertIs(NullableJSONModel.objects.filter(value__c__lt=5).exists(), False) + def test_lookup_exclude(self): + tests = [ + (Q(value__a='b'), [self.objs[0]]), + (Q(value__foo='bax'), [self.objs[0], self.objs[7]]), + ] + for condition, expected in tests: + self.assertSequenceEqual( + NullableJSONModel.objects.exclude(condition), + expected, + ) + self.assertSequenceEqual( + NullableJSONModel.objects.filter(~condition), + expected, + ) + + def test_lookup_exclude_nonexistent_key(self): + # Values without the key are ignored. + condition = Q(value__foo='bax') + objs_with_value = [self.objs[6]] + objs_with_different_value = [self.objs[0], self.objs[7]] + self.assertSequenceEqual( + NullableJSONModel.objects.exclude(condition), + objs_with_different_value, + ) + self.assertSequenceEqual( + NullableJSONModel.objects.exclude(~condition), + objs_with_value, + ) + self.assertCountEqual( + NullableJSONModel.objects.filter(condition | ~condition), + objs_with_value + objs_with_different_value, + ) + self.assertCountEqual( + NullableJSONModel.objects.exclude(condition & ~condition), + objs_with_value + objs_with_different_value, + ) + # Add the __isnull lookup to get an exhaustive set. + self.assertSequenceEqual( + NullableJSONModel.objects.exclude(condition & Q(value__foo__isnull=False)), + self.objs[0:6] + self.objs[7:], + ) + self.assertSequenceEqual( + NullableJSONModel.objects.filter(condition & Q(value__foo__isnull=False)), + objs_with_value, + ) + @skipIf( connection.vendor == 'oracle', 'Raises ORA-00600: internal error code on Oracle 18.',