Created
September 26, 2011 23:09
-
-
Save wojtyniak/1243699 to your computer and use it in GitHub Desktop.
serializable paginator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SerializablePaginator(object): | |
def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True): | |
self.object_list = object_list | |
self.per_page = per_page | |
self.orphans = orphans | |
self.allow_empty_first_page = allow_empty_first_page | |
self._num_pages = self._count = None | |
def validate_number(self, number): | |
"Validates the given 1-based page number." | |
try: | |
number = int(number) | |
except ValueError: | |
raise PageNotAnInteger('That page number is not an integer') | |
if number < 1: | |
raise EmptyPage('That page number is less than 1') | |
if number > self.num_pages: | |
if number == 1 and self.allow_empty_first_page: | |
pass | |
else: | |
raise EmptyPage('That page contains no results') | |
return number | |
def page(self, number): | |
"Returns a Page object for the given 1-based page number." | |
number = self.validate_number(number) | |
bottom = (number - 1) * self.per_page | |
top = bottom + self.per_page | |
if top + self.orphans >= self.count: | |
top = self.count | |
return Page(self.object_list[bottom:top], number, self) | |
def _get_count(self): | |
"Returns the total number of objects, across all pages." | |
if self._count is None: | |
try: | |
self._count = self.object_list.count() | |
except (AttributeError, TypeError): | |
# AttributeError if object_list has no count() method. | |
# TypeError if object_list.count() requires arguments | |
# (i.e. is of type list). | |
self._count = len(self.object_list) | |
return self._count | |
count = property(_get_count) | |
def _get_num_pages(self): | |
"Returns the total number of pages." | |
if self._num_pages is None: | |
if self.count == 0 and not self.allow_empty_first_page: | |
self._num_pages = 0 | |
else: | |
hits = max(1, self.count - self.orphans) | |
self._num_pages = int(ceil(hits / float(self.per_page))) | |
return self._num_pages | |
num_pages = property(_get_num_pages) | |
def _get_page_range(self): | |
""" | |
Returns a 1-based range of pages for iterating through within | |
a template for loop. | |
""" | |
return range(1, self.num_pages + 1) | |
page_range = property(_get_page_range) | |
def __getstate__(self): | |
self._get_count() | |
self._get_num_pages() | |
odict = self.__dict__.copy() | |
odict['object_list'] = None | |
#odict['model'] = self.object_list.model #one powinny być serializowane, ale nie wchodzą do memcache'a nie wiem dlaczego | |
#odict['query'] = self.object_list.query | |
#odict['db'] = self.object_list.db | |
return odict | |
# w związku z powyższym komentarzem nie ma potrzeby odtwarzać zapytania | |
# def __setstate__(self, state): | |
# state['object_list'] = QuerySet(state['model'], state['query'], state['db']) | |
# del state['model'] | |
# del state['query'] | |
# del state['db'] | |
# self.__dict__.update(state) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment