|
@@ -0,0 +1,167 @@
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+
|
|
|
+from math import ceil
|
|
|
+
|
|
|
+from sqlalchemy import text
|
|
|
+
|
|
|
+
|
|
|
+def slice_list(list, slice_into):
|
|
|
+ for i in xrange(0, len(list), slice_into):
|
|
|
+ yield list[i:i + slice_into]
|
|
|
+
|
|
|
+class BasePages(object):
|
|
|
+
|
|
|
+ def __init__(self, Query, page, per_page):
|
|
|
+ self.page = page
|
|
|
+ self.per_page = per_page
|
|
|
+ self.Query = Query
|
|
|
+ self.total_count = self._load_count()
|
|
|
+
|
|
|
+ def _load_count(self):
|
|
|
+ raise NotImplementedError()
|
|
|
+
|
|
|
+ @property
|
|
|
+ def pages(self):
|
|
|
+ return int(ceil(self.total_count / float(self.per_page)))
|
|
|
+
|
|
|
+ @property
|
|
|
+ def has_prev(self):
|
|
|
+ return self.page > 1
|
|
|
+
|
|
|
+ @property
|
|
|
+ def has_next(self):
|
|
|
+ return self.page < self.pages
|
|
|
+
|
|
|
+ def iter_pages(self, left_edge=2, left_current=2, right_current=5, right_edge=2):
|
|
|
+ last = 0
|
|
|
+ for num in xrange(1, self.pages + 1):
|
|
|
+ if num <= left_edge or \
|
|
|
+ (num > self.page - left_current - 1 and \
|
|
|
+ num < self.page + right_current) or \
|
|
|
+ num > self.pages - right_edge:
|
|
|
+ if last + 1 != num:
|
|
|
+ yield None
|
|
|
+ yield num
|
|
|
+ last = num
|
|
|
+
|
|
|
+ def list(self):
|
|
|
+ raise NotImplementedError()
|
|
|
+
|
|
|
+class SqlalchemyPages(BasePages):
|
|
|
+ def _load_count(self):
|
|
|
+ return self.Query.count()
|
|
|
+
|
|
|
+ def list(self):
|
|
|
+ return self.Query.offset((self.page-1)*self.per_page)\
|
|
|
+ .limit(self.per_page).all()
|
|
|
+
|
|
|
+class SqlPages(BasePages):
|
|
|
+ def __init__(self, Query, page, per_page, db, **query_args):
|
|
|
+ self.query_args = query_args
|
|
|
+ self.db = db
|
|
|
+ super(SqlPages, self).__init__(
|
|
|
+ self._remove_dotted(Query), page, per_page)
|
|
|
+
|
|
|
+ def _remove_dotted(self, sql):
|
|
|
+ return sql.strip()[:-1] if sql.strip().endswith(";") else sql
|
|
|
+
|
|
|
+ def sum(self, *group_args):
|
|
|
+ group_sql = "SELECT %s FROM (%s) T;" % (
|
|
|
+ ", ".join([ "SUM(%s) %s" % (x, x) for x in group_args ]),
|
|
|
+ self.Query
|
|
|
+ )
|
|
|
+ record = self.db.session.execute(text(group_sql), self.query_args)
|
|
|
+ rv = []
|
|
|
+ for row in record.fetchall():
|
|
|
+ row_dict = dict(zip(row.keys(), row))
|
|
|
+ rv.append(row_dict)
|
|
|
+ return rv[0]
|
|
|
+
|
|
|
+ def _load_count(self):
|
|
|
+ count_sql = "SELECT COUNT(*) c FROM (%s) t;" % self.Query
|
|
|
+ record = self.db.session.execute(text(count_sql), self.query_args)
|
|
|
+ count = record.fetchone()
|
|
|
+ return count[0]
|
|
|
+
|
|
|
+ def list(self):
|
|
|
+ query_sql = "%s offset %s limit %s;" % (
|
|
|
+ self.Query,
|
|
|
+ (self.page-1)*self.per_page,
|
|
|
+ self.per_page
|
|
|
+ )
|
|
|
+ record = self.db.session.execute(text(query_sql), self.query_args)
|
|
|
+ rv = []
|
|
|
+ for row in record.fetchall():
|
|
|
+ row_dict = dict(zip(row.keys(), row))
|
|
|
+ rv.append(row_dict)
|
|
|
+ return rv
|
|
|
+
|
|
|
+class ListPages(BasePages):
|
|
|
+ def _load_count(self):
|
|
|
+ return len(self.Query)
|
|
|
+
|
|
|
+ def list(self):
|
|
|
+ object_list = []
|
|
|
+
|
|
|
+ for list in slice_list(self.Query, self.per_page):
|
|
|
+ object_list.append(list)
|
|
|
+
|
|
|
+ if not object_list:
|
|
|
+ object_list = [[]]
|
|
|
+ try:
|
|
|
+ result = object_list[self.page-1]
|
|
|
+ except IndexError:
|
|
|
+ result = object_list[0]
|
|
|
+ return result
|
|
|
+
|
|
|
+def object_list(Query, per_page, page):
|
|
|
+
|
|
|
+ object_list = []
|
|
|
+
|
|
|
+ for list in slice_list(Query, per_page):
|
|
|
+ object_list.append(list)
|
|
|
+
|
|
|
+ if not object_list:
|
|
|
+ object_list = [[]]
|
|
|
+ try:
|
|
|
+ result = object_list[page-1]
|
|
|
+ except IndexError:
|
|
|
+ result = object_list[0]
|
|
|
+ return result
|
|
|
+
|
|
|
+class Pages(object):
|
|
|
+ def __init__(self, Query, page, per_page):
|
|
|
+ self.page = page
|
|
|
+ self.per_page = per_page
|
|
|
+ try:
|
|
|
+ self.total_count = Query.row_count
|
|
|
+ except Exception as e:
|
|
|
+ self.total_count = Query
|
|
|
+
|
|
|
+ @property
|
|
|
+ def pages(self):
|
|
|
+ return int(ceil(self.total_count / float(self.per_page)))
|
|
|
+
|
|
|
+
|
|
|
+ @property
|
|
|
+ def has_prev(self):
|
|
|
+ return self.page > 1
|
|
|
+
|
|
|
+
|
|
|
+ @property
|
|
|
+ def has_next(self):
|
|
|
+ return self.page < self.pages
|
|
|
+
|
|
|
+
|
|
|
+ def iter_pages(self, left_edge=2, left_current=2,
|
|
|
+ right_current=5, right_edge=2):
|
|
|
+ last = 0
|
|
|
+ for num in xrange(1, self.pages + 1):
|
|
|
+ if num <= left_edge or \
|
|
|
+ (num > self.page - left_current - 1 and \
|
|
|
+ num < self.page + right_current) or \
|
|
|
+ num > self.pages - right_edge:
|
|
|
+ if last + 1 != num:
|
|
|
+ yield None
|
|
|
+ yield num
|
|
|
+ last = num
|