fix precedence of ~ operator in Q objects

This commit is contained in:
mangototango 2021-10-21 05:33:23 +00:00
parent 0787efc1cc
commit 3b0aaebe50
2 changed files with 14 additions and 2 deletions

View File

@ -209,10 +209,10 @@ class Q(object):
@classmethod @classmethod
def _construct_from(cls, l_child, r_child, mode): def _construct_from(cls, l_child, r_child, mode):
if mode == l_child._mode: if mode == l_child._mode and not l_child._negate:
q = deepcopy(l_child) q = deepcopy(l_child)
q._children.append(deepcopy(r_child)) q._children.append(deepcopy(r_child))
elif mode == r_child._mode: elif mode == r_child._mode and not r_child._negate:
q = deepcopy(r_child) q = deepcopy(r_child)
q._children.append(deepcopy(l_child)) q._children.append(deepcopy(l_child))
else: else:

View File

@ -302,6 +302,18 @@ class QuerySetTestCase(TestCaseWithData):
self.assertEqual(qs.conditions_as_sql(), self.assertEqual(qs.conditions_as_sql(),
"(first_name = 'a') AND (greater(`height`, 1.7)) AND (last_name = 'b')") "(first_name = 'a') AND (greater(`height`, 1.7)) AND (last_name = 'b')")
def test_precedence_of_negation(self):
p = ~Q(first_name='a')
q = Q(last_name='b')
r = p & q
self.assertEqual(r.to_sql(Person), "(last_name = 'b') AND (NOT (first_name = 'a'))")
r = q & p
self.assertEqual(r.to_sql(Person), "(last_name = 'b') AND (NOT (first_name = 'a'))")
r = q | p
self.assertEqual(r.to_sql(Person), "(last_name = 'b') OR (NOT (first_name = 'a'))")
r = ~q & p
self.assertEqual(r.to_sql(Person), "(NOT (last_name = 'b')) AND (NOT (first_name = 'a'))")
def test_invalid_filter(self): def test_invalid_filter(self):
qs = Person.objects_in(self.database) qs = Person.objects_in(self.database)
with self.assertRaises(TypeError): with self.assertRaises(TypeError):