基于Sqlalchemy 实现的分页器 QueryPaginate

问:为什么不用Sqlalchemy自带的 paginate 呢?
答:Sqlalchemy自带的paginate在实际应用中有所不足,不符合国内用户的习惯,且无法保证选择项一直居中

问:此QueryPaginate是否存在性能问题
答:此分页器已在多项目上使用发现counts()求值上存在性能问题,100w select 50s

图1.分页器类包含的参数见图

图2.在分页列表内选中项始终居中

上代码

    def __init__(self, query, per_page: int = 30, page: int = 1):
        """ 初始化分页参数 :param query: 查询对象 :param per_page: 一页多少内容 :param page: 第几页 1起 """
        self.query = query
        self.per_page = per_page
        self.page = page

    @property
    def items(self):
        """ 得到分页后的内容 :return: [model row / Model] """
        if self.page > self.pages:
            return []
        offset_num = self.page - 1 * 30
        return self.query.limit(self.per_page).offset(offset_num).all()

    @property
    def counts(self):
        """ 总数据量 :return: int """
        return self.query.count()

    @property
    def pages(self):
        """ 总页数 :return: int """
        return ceil(self.counts / self.per_page)

    @property
    def next_num(self):
        """下一页"""
        next_num = self.page + 1
        if self.pages < next_num:
            return None
        return next_num

    @property
    def prev_num(self):
        """上一页"""
        prev_num = self.page - 1
        if prev_num < 1:
            return None
        return prev_num

    def iter_pages(self, left=2, right=2):
        length = left + right + 1
        # 页数大于
        if self.page > self.pages:
            range_start = self.pages - length
            if range_start <= 0:
                range_start = 1
            return range(range_start, self.pages + 1)

        # 页数小于最少分页数
        if self.pages < length:
            return range(1, self.pages + 1)

        # 页数正常的情况下,至少大于 length 长度
        l_boundary, r_boundary = left + 1, self.pages - right + 1
        if l_boundary < self.page < r_boundary:
            return range(self.page - left, self.page + right + 1)
        if self.page <= left:
            return range(1, length + 1)
        return range(self.pages - length, self.pages + 1)

if main == '__mian__':
	paginate = QueryPaginate(query=Permission.query, per_page=per_page, page=pages)
	paginate.iter_pages() # 显示在前端的页码列表
	paginate.items # 分页后的数据 []
	paginate.pages # 共xxx页
	paginate.page # 当前页码 从1开始
	paginate.per_page # 一页几行
	paginate.prev_num # 上一页页码
	paginate.next_num # 下一页页码

觉得有用别忘了点赞,评论,关注一下哦

本文地址:https://blog.csdn.net/weixin_43874226/article/details/110427332