From f997c81472b96a1cf48a1a19a4fe974683455a50 Mon Sep 17 00:00:00 2001 From: Hasan Ramezani Date: Thu, 23 Sep 2021 18:40:54 +0200 Subject: [PATCH] Fixed #33127 -- Added error messages on | and & operators with combined querysets. --- django/db/models/query.py | 6 ++++++ tests/queries/test_qs_combinators.py | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/django/db/models/query.py b/django/db/models/query.py index 1bc8e2ed2a..661ebd1f24 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -325,6 +325,7 @@ class QuerySet: return cls def __and__(self, other): + self._check_operator_queryset(other, '&') self._merge_sanity_check(other) if isinstance(other, EmptyQuerySet): return other @@ -336,6 +337,7 @@ class QuerySet: return combined def __or__(self, other): + self._check_operator_queryset(other, '|') self._merge_sanity_check(other) if isinstance(self, EmptyQuerySet): return other @@ -1430,6 +1432,10 @@ class QuerySet: % (operation_name, self.query.combinator) ) + def _check_operator_queryset(self, other, operator_): + if self.query.combinator or other.query.combinator: + raise TypeError(f'Cannot use {operator_} operator with combined queryset.') + class InstanceCheckMeta(type): def __instancecheck__(self, instance): diff --git a/tests/queries/test_qs_combinators.py b/tests/queries/test_qs_combinators.py index 351a401902..89d08ef6db 100644 --- a/tests/queries/test_qs_combinators.py +++ b/tests/queries/test_qs_combinators.py @@ -441,3 +441,24 @@ class QuerySetSetOperationTests(TestCase): with self.subTest(combinator=combinator): with self.assertRaisesMessage(NotSupportedError, msg % combinator): getattr(qs, combinator)(qs).get(num=2) + + def test_operator_on_combined_qs_error(self): + qs = Number.objects.all() + msg = 'Cannot use %s operator with combined queryset.' + combinators = ['union'] + if connection.features.supports_select_difference: + combinators.append('difference') + if connection.features.supports_select_intersection: + combinators.append('intersection') + operators = [ + ('|', operator.or_), + ('&', operator.and_), + ] + for combinator in combinators: + combined_qs = getattr(qs, combinator)(qs) + for operator_, operator_func in operators: + with self.subTest(combinator=combinator): + with self.assertRaisesMessage(TypeError, msg % operator_): + operator_func(qs, combined_qs) + with self.assertRaisesMessage(TypeError, msg % operator_): + operator_func(combined_qs, qs)