Login

Basic CouchDB Paginator (Updated)

Author:
toke
Posted:
November 20, 2008
Language:
Python
Version:
1.0
Score:
0 (after 0 ratings)

This is a very basic paginator for CouchDB ViewResults. It's usage is similar to the django one.

CouchPaginator is almost like the django version with one exception: It's constructor needs an additional argument pages_view which is either a reduce result or an integer which holds the total number of objects across all pages.

Example Map/Reduce for pages:

map = function(doc) { if(doc.type=="application" || doc.type=="inquiry"){ emit([doc.meta.user.toLowerCase(), doc.type], 1); } reduce = function (doc, value, rereduce){ return sum(value); }

SimpleCouchPaginator is much simpler and needs no total number and can only paginate by "next" and "previous" page. Use this if you don't have an reduce view which tells you the amount of total object.

An Example setup of CouchDB with django can be found at: Eric Florenzanos post about django+couchdb

See example usage

  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
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
# -*- 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

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 8 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 3 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
  5. Help text hyperlinks by sa2812 1 year, 5 months ago

Comments

Please login first before commenting.