# -*- coding: utf-8 -*-
from math import ceil
from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage
class CouchPaginator(Paginator):
"""Allows pagination of couchdb-python ViewResult objects. """
def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True, pages_view=None):
self.per_page = per_page
self._object_list = object_list
self.orphans = orphans
self.allow_empty_first_page = allow_empty_first_page
self._pages_view = pages_view
self._num_pages = None
def page(self, number):
"Returns a Page object for the given 1-based page number."
self._number = self.validate_number(number)
skip = self._number * self.per_page - self.per_page
### FIXME it would be nice to be compatible with django
### and allow [from:to] syntax
self._object_list.options['count'] = self.per_page + 1
self._object_list.options['skip'] = skip
return Page(self.object_list, self._number, self)
@property
def _count(self):
"""Implementation specific object count (overall)"""
if self._pages_view:
if isinstance(self._pages_view, int):
count = self._pages_view
else:
count = self._pages_view.rows[0].get("value", None)
else:
count = None
return count
@property
def object_list(self):
"""Returns a list of results or raises EmptyPage"""
if self._object_list:
return list(self._object_list)[:self.per_page]
else:
raise EmptyPage('That page contains no results')
class SimpleCouchPaginator(CouchPaginator):
"""Allows very simple page by page pagination with CouchDB ViewResults
use SimpleCouchPaginator only if you don't have the absolute object count.
If you have it CouchPaginator would be fine.
"""
def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
self.per_page = per_page
self._object_list = object_list
self.orphans = orphans
self.allow_empty_first_page = allow_empty_first_page
self._num_pages = None
return super(SimpleCouchPaginator, self).__init__(object_list, per_page,
orphans=orphans, allow_empty_first_page=allow_empty_first_page)
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')
return number
def _get_count(self):
return False
@property
def num_pages(self):
return False
@property
def object_count(self):
return len(list(self._object_list))
@property
def next(self):
if self.has_next:
return self._number + 1
else:
return None
@property
def previous(self):
if self.has_previous:
return self._number - 1
else:
return None
@property
def has_next(self):
return self.object_count > self.per_page
@property
def has_previous(self):
return self._number > 1
Comments