欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python 基于Sqlalchemy实现的分页器 QueryPaginate

程序员文章站 2022-03-27 12:56:39
基于Sqlalchemy 实现的分页器 QueryPaginate问:为什么不用Sqlalchemy自带的 paginate 呢?答:Sqlalchemy自带的paginate在实际应用中有所不足,不符合国内用户的习惯,且无法保证选择项一直居中问:此QueryPaginate是否存在性能问题答:此分页器已在多项目上使用,不存在此问题图1.分页器类包含的参数见图图2.在分页列表内选中项始终居中上代码 def __init__(self, query, per_page: int =...

基于Sqlalchemy 实现的分页器 QueryPaginate

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

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

图1.分页器类包含的参数见图
Python 基于Sqlalchemy实现的分页器 QueryPaginate
图2.在分页列表内选中项始终居中
Python 基于Sqlalchemy实现的分页器 QueryPaginate

上代码

    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