Login

(Modified/Improved) MultiQuerySet

Author:
joonas
Posted:
December 17, 2008
Language:
Python
Version:
1.0
Tags:
multiple queryset chain
Score:
0 (after 0 ratings)

My modified version of the MultiQuerySet by mattdw (see the link for further information).

My purpose for this was to enable me to combine multiple different types of querysets together, which could then be iterated on as one object (i.e. like a tumblelog).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class MultiQuerySet(object):
    def __init__(self, *args, **kwargs):
        self.querysets = args
        self._count = None
    
    def _clone(self):
        querysets = [qs._clone() for qs in self.querysets]
        return MultiQuerySet(*querysets)
    
    def __repr__(self):
        return repr(list(self.querysets))
                
    def count(self):
        if not self._count:
            self._count = sum([qs.count() for qs in self.querysets])
        return self._count
    
    def __len__(self):
        return self.count()
    
    def __iter__(self):
        for qs in self.querysets:
            for item in qs.all():
                yield item
        
    def __getitem__(self, item):
        indices = (offset, stop, step) = item.indices(self.count())
        items = []
        total_len = stop - offset
        for qs in self.querysets:
            if len(qs) < offset:
                offset -= len(qs)
            else:
                items += list(qs[offset:stop])
                if len(items) >= total_len:
                    return items
                else:
                    offset = 0
                    stop = total_len - len(items)
                    continue

More like this

  1. SearchableManager by stephen_mcd 5 years ago
  2. Chain multiple querysets into one by mattdw 6 years, 5 months ago
  3. Generic object_detail view with multiple named URL filters by cotton 3 years, 2 months ago
  4. Annotate queryset with comment count by fivethreeo 6 years, 5 months ago
  5. Memory efficient Django Queryset Iterator by WoLpH 5 years ago

Comments

nosa_manuel (on December 18, 2008):

It would be nice to have these generated transparently:

class QuerySet(object):
    ...
    def __add__(self, other):
        if isinstance(other, QuerySet):
            return MultiQuerySet(self, other)
        elif isinstance(other, MultiQuerySet):
            querysets = other._clone().querysets
            return MultiQuerySet(self, *querysets)
        else:
            raise TypeError

#

esquevin (on October 19, 2012):

I've fixed a bug in the code that occurred with small querysets on pages > 1, the length of former queryset was substracted from the offset, but not from the stop, resulting in variable length pages

def __getitem__(self, item):
    indices = (offset, stop, step) = item.indices(self.count())
    items = []
    total_len = stop - offset
    for qs in self.querysets:
        if len(qs) < offset:
            offset -= len(qs)
        else:
            items += list(qs[offset:offset + total_len - len(items)])
            if len(items) >= total_len:
                return items
            else:
                offset = 0
                continue

#

Please login first before commenting.