Commits

Anonymous committed 7c3123f

[svn] First go at paginate with orm helpers

Comments (0)

Files changed (2)

webhelpers/pagination/__init__.py

-"""Pagination functions and wrappers"""
-from orm import *
+"""Pagination for Collections and ORMs
 
+The Pagination module aids in the process of paging large collections of
+objects. It can be used macro-style for automatic fetching of large collections
+using one of the ORM wrappers, or handle a large collection responding to
+standard Python list slicing operations. These methods can also be used
+individually and customized to do as much or little as desired.
+
+The Paginator itself maintains pagination logic associated with each page, where
+it begins, what the first/last item on the page is, etc.
+
+Helper functions hook-up the Paginator in more conveinent methods for the more
+macro-style approach to return the Paginator and the slice of the collection
+desired.
+
+"""
+from routes import request_config
+from orm import get_wrapper
+
+def paginate(collection, page=None, per_page=10, *args, **options):
+    """Paginate a collection of data
+    
+    If the collection is a list, it will return the slice of the list along
+    with the Paginator object. If the collection is given using an ORM, the
+    collection argument must be a partial representing the function to be
+    used that will generate the proper query and extend properly for the
+    limit/offset.
+    
+    """
+    collection = get_wrapper(collection, *args, **options)
+    count = len(collection)
+    page = getattr(request_config(), environ, {}).get('QUERY_ARGS')
+    paginator = Paginator(count, per_page, page)
+    subset = collection[paginator.current.first_item-1:paginator.current.last_item]
+    
+    return paginator, subset
+    
+    
 class Paginator(object):
     def __init__(self, item_count, items_per_page=10, current_page=1):
         self.item_count = item_count
         if padding < 0: self._padding = 0
         first_page_in_window = self.page.number - self._padding
         self.first = first_page_in_window in self.paginator and (
-        self.paginator[first_page_in_window]) or self.paginator.first
+            self.paginator[first_page_in_window]) or self.paginator.first
         last_page_in_window = self.page.number + self._padding
         self.last = last_page_in_window in self.paginator and (
-        self.paginator[last_page_in_window]) or self.paginator.last
+            self.paginator[last_page_in_window]) or self.paginator.last
 
     def padding__get(self):
         return self._padding

webhelpers/pagination/orm.py

+"""ORM Wrappers"""
+from webhelpers.util import Partial
+
+orms = {}
+try:
+    import sqlobject
+except:
+    pass
+else:
+    orms['sqlobject'] = True
+try:
+    import sqlalchemy
+except:
+    pass
+else:
+    orms['sqlalchemy'] = True
+
+def get_wrapper(obj, *args, **kw):
+    if isinstance(obj, list):
+        return obj
+    if orms.get('sqlobject'):
+        if issubclass(obj, sqlobject.SQLObject):
+            return SQLObjectLazy(obj.select, *args, **kw)
+    if orms.get('sqlalchemy'):
+        return SQLAlchemyLazy(obj.select, *args, **kw)
+
+class SQLObjectLazy(Partial):
+    def __getitem__(self, key):
+        if not isinstance(key, slice):
+            raise Exception, "SQLObjectLazy doesn't support getitem without slicing"
+        limit = key.stop - key.start + 1
+        offset = key.start
+        return list(self().limit(limit).offset(offset))
+    
+    def __len__(self):
+        return self().count()
+
+class SQLAlchemyLazy(Partial):
+    def __getitem__(self, key):
+        if not isinstance(key, slice):
+            raise Exception, "SQLAlchemyLazy doesn't support getitem without slicing"
+        limit = key.stop - key.start + 1
+        offset = key.start
+        return self(limit=limit, offset=offset).execute()
+    
+    def __len__(self):
+        pass
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.