Fixed #27718 -- Added QuerySet.union(), intersection(), difference().

Thanks Mariusz Felisiak for review and Oracle assistance.
Thanks Tim Graham for review and writing docs.
This commit is contained in:
Florian Apolloner 2017-01-14 14:32:07 +01:00 committed by Tim Graham
parent 611ef422b1
commit 84c1826ded
12 changed files with 323 additions and 51 deletions

View file

@ -816,6 +816,33 @@ class QuerySet(object):
else:
return self._filter_or_exclude(None, **filter_obj)
def _combinator_query(self, combinator, *other_qs, **kwargs):
# Clone the query to inherit the select list and everything
clone = self._clone()
# Clear limits and ordering so they can be reapplied
clone.query.clear_ordering(True)
clone.query.clear_limits()
clone.query.combined_queries = (self.query,) + tuple(qs.query for qs in other_qs)
clone.query.combinator = combinator
clone.query.combinator_all = kwargs.pop('all', False)
return clone
def union(self, *other_qs, **kwargs):
if kwargs:
unexpected_kwarg = next((k for k in kwargs.keys() if k != 'all'), None)
if unexpected_kwarg:
raise TypeError(
"union() received an unexpected keyword argument '%s'" %
(unexpected_kwarg,)
)
return self._combinator_query('union', *other_qs, **kwargs)
def intersection(self, *other_qs):
return self._combinator_query('intersection', *other_qs)
def difference(self, *other_qs):
return self._combinator_query('difference', *other_qs)
def select_for_update(self, nowait=False, skip_locked=False):
"""
Returns a new QuerySet instance that will select objects with a