Skip to content

Instantly share code, notes, and snippets.

@BradWhittington
Created April 6, 2011 17:03
Show Gist options
  • Save BradWhittington/906050 to your computer and use it in GitHub Desktop.
Save BradWhittington/906050 to your computer and use it in GitHub Desktop.
Class which takes multiple django querysets and returns an optionally sorted, merged version
Usage is:
OrderedMixedQuerysets('-date',MyModel.objects.all(),MyOtherModel.objects.all())
#Inspired by http://stackoverflow.com/questions/431628/how-to-combine-2-or-more-querysets-in-a-django-view
class OrderedMixedQuerysets:
reverse = False
def __init__(self, order_by, *querysets):
self.querysets = querysets
self.order_by = order_by
if self.order_by and self.order_by.startswith('-'):
self.reverse = True
self.order_by = self.order_by[1:]
def count(self):
"""
Performs a .count() for all subquerysets and returns the number of
records as an integer.
"""
return sum(qs.count() for qs in self.querysets)
def _clone(self):
"Returns a clone of this queryset chain"
return self.__class__(*self.querysets, order_by=self.order_by)
def all(self):
"Iterates records in all subquerysets"
if self.order_by:
object_list = sorted(chain(*self.querysets), key=attrgetter(self.order_by))
if self.reverse:
object_list = reversed(object_list)
else:
object_list = chain(*self.querysets)
return object_list
def __getitem__(self, ndx):
if type(ndx) is slice:
return list(islice(self.all(), ndx.start, ndx.stop, ndx.step or 1))
else:
return islice(self.all(), ndx, ndx+1).next()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment