flask框架中分页的使用,过滤条件的执行流程,查用户列表代码示范

针对sqlalchemy模块的分页使用


pip install pagination  # 安装模块

--------------------------------------------------------------
# 该模块代码
def int_ceil(x, y):
    """
    equivalent to math.ceil(x / y)
    :param x:
    :param y:
    :return:
    """
    q, r = divmod(x, y)
    if r:
        q += 1
    return q


class Pagination(object):
    def __init__(self, query, page=1, per_page=10, per_nav=10,
                 map_=lambda x: x):
        self.first = 1
        self.total = query.count()
        if self.total == 0:
            self.last = 1
        else:
            self.last = int_ceil(self.total, per_page)
        self.page = max(min(self.last, page), 1)

        self.prev = max(self.page - 1, 1)
        self.has_prev = self.prev != self.page
        self.next = min(self.page + 1, self.last)
        self.has_next = self.next != self.page

        self.nav_head = per_nav * (int_ceil(self.page, per_nav) - 1) + 1
        self.nav_tail = min(self.last, self.nav_head + per_nav - 1)

        self.nav_prev = max(self.page - per_nav, 1)
        self.has_nav_prev = self.nav_prev < self.nav_head
        self.nav_next = min(self.page + per_nav, self.last)
        self.has_nav_next = self.nav_next > self.nav_tail

        self.pages = range(self.nav_head, self.nav_tail + 1)

        start = (self.page - 1) * per_page
        self.items = map(map_, query[start: start + per_page])


# 该模块里面总共就这么点代码,甚至可以把该代码直接复制过来,以后就不用下载该模块了

---------------------------------------------------------------------


# 使用步骤

# 该分页类适用于 使用sqlalchemy模块产生连接对象,然后通过该连接对象实现的查所有功能中的分页功能!!!


from sqlalchemy_paginate import Pagination

# 把查所有的query对象放到该分页类的括号里面
query = db_session.query(你要查的表名)
pagination = Pagination(query, page=3, per_page=2)

# 生成的对象再点items 就拿到了对应的 第3页的两条数据对象了
for obj in pagination.items:
    print(obj.name)

--------------------------------------------------------------------------

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

flask-sqlalchemy 的分页使用

flask-sqlalchemy的db对象可以直接点paginate方法传对应的参数,就可以直接生成pagination对象

通过这个pagination对象既可以拿到对应的查询后的query,还可拿到分页的乱七八糟信息


# 这个是自己写的函数
def get_pagination_dict(pagination) -> dict:
    '''
    通过BaseQuery的Pagination实例,返回标准的分页返回体
    '''
    if pagination is None:
        return None

    return {
        'has_next': pagination.has_next,
        'has_prev': pagination.has_prev,
        'page': pagination.page,
        'pages': pagination.pages,
        'total': pagination.total,
        'per_page': pagination.per_page,
        'page_item_num': len(pagination.items),
    }

----------------------------------------

@auth_blueprint.route('/list_accounts', methods=['POST'])
@token_required_with_user
def list_accounts(user):
    '''
    本平台系统用户列表
    '''
    if user.group_id not in [0, 1]:
        return jsonify_return_body(['result', 'code', 'msg'], result=False, msg='账号无权限调用本接口')

    filters = []

    pagination = {
        'page': 1,
        'per_page': 10
    }

    order_by = [
        {'key': 'auth_user.username', 'desc': True}
    ]

    order_by = generate_orderby_text(order_by)

    if 'pageIndex' in request.json.keys():
        pagination['page'] = request.json['pageIndex']

    if 'pageSize' in request.json.keys():
        pagination['per_page'] = request.json['pageSize']

    if 'orderBy' in request.json.keys():
        order_by = request.json['orderBy']

    query_users = db_sqlalchemy.session.query(AuthUser, AuthGroup, BizUnit, ConstBizUnitType) \
        .select_from(AuthUser) \
        .outerjoin(AuthGroup, AuthUser.group_id == AuthGroup.id) \
        .outerjoin(BizUnit, AuthUser.biz_unit_id == BizUnit.id) \
        .outerjoin(ConstBizUnitType, BizUnit.type == ConstBizUnitType.id) \
        .filter(*filters) \
        .where(AuthUser.group_id != 0) \
        .order_by(order_by)

    pagination = query_users.paginate(page=pagination['page'], per_page=pagination['per_page'], error_out=True,
                                      max_per_page=None)

    return jsonify_return_body(
        body_key_list=['code', 'msg', 'data', 'pagination'],
        result=True,
        data=[formatter_account_info_in_list(user, *i) for i in pagination.items],
        pagination=get_pagination_dict(pagination)
    )


# 关键点就是用query点paginate(page=xx,per_page=yy, error_out=True,max_per_page=None)生成
# 一个已经是分页后的当前页的pagination对象,此时应该还是一个类似于query的东西

# 最后用这个当前页的pagination对象去点items 获取当前页的pagination对象里面所包含的所有元素
# 就是一个查所有,然后根据分页条件,过滤出,包含当前页所有元素的query来,
# 最后点items就类似于query.all()  获取列表里的所有对象!!!

# 其他参数用法参考博客 https://blog.csdn.net/weixin_44420527/article/details/106886332

.
.
.
.
.
.
.
.
.
.

过滤条件的执行流程


# 很多情况下,我们会存在多个过滤条件的情况
# 注意在flask的orm语句中,只要还没有点first() 或者点all() 这些
# orm语句的执行结果是一个query ,就是一个sql查询语句  还没有进行数据库查询操作了!!!
# 只要还是query ,就可以继续去filter等操作

# 假设我们一开始的时候orm得到的query是一个字段过滤条件的sql查询语句
# 我们需要再第一次的query的基础上继续点filter的时候,那么这一次的过滤条件,实际上最终
# 转化成sql语句,就是把过滤条件与上次的过滤条件,通过and连接起来,做了与的操作
# 也就是既满足第一次的过滤条件,也要满足第二次的过滤条件!!!
# 就是多个过滤条件都是and连接,需要同时满足!!!


# 测试
@project_blueprint.route('/find_list111', methods=["GET", ])
@token_required
def find_list111():
    query = db_sqlalchemy.session.query(ProjectDtw)
    print(query, '111111111111')
    # SELECT id, name, create_by_user_id, img_url, status FROM project_dtw

    query = query.filter(ProjectDtw.id < 8)
    # SELECT id, name, create_by_user_id, img_url, status FROM project_dtw WHERE id < 8
    print(query, '222222222222')

    query = query.filter(ProjectDtw.id >2)
    # SELECT id, name, create_by_user_id, img_url, status FROM project_dtw WHERE id < 8 and id > 2
    print(query, '333333333333')

    page = int(request.args.get('page', 1))
    per_page = int(request.args.get('per_page', 20))
    pagination = query.paginate(page=page, per_page=per_page, error_out=True,
                                max_per_page=None)

    print(pagination)
    # <flask_sqlalchemy.pagination.QueryPagination object at 0x000001E5F7902B50>

    print(pagination.items)  # [符合分页条件的对象1,对象2。。。 ]

    info_list = []
    for obj in pagination.items:
        create_by_user_id = obj.create_by_user_id
        info_list.append({'id': obj.id, 'name': obj.name,
                          'img_url': obj.img_url, 'status': obj.status,
                          })


    return jsonify_return_body(
        body_key_list=['code', 'msg', 'data', 'pagination'],
        result=True,
        data=info_list,
        pagination=get_pagination_dict(pagination)
    )

.
.
.
.
.
.

查用户列表代码示范


查所有用户,可以分页,可以排序,然后可以根据传的字段进行过滤
根据用户名模糊匹配,根据role_id精准过滤,根据group_id精准过滤
根据group_id_list 只要用户属于该group_id_list里任意一个组,就可过滤出来
根据group_id_all_in_list  用户所属的组,必须要全部满足group_id_all_in_list里所有组,才能被
过滤出来!!!

----------------------------

@blueprint.route('/user_find_list', methods=['POST'])
@body_type_is_dict
def user_find_list():
    """
    用户列表查询
    """

    filters = list()

    order_by = [{'key': 'auth_user.id', 'desc': True}]

    use_group_filter = False
    use_group_all_in_filter = False

    if 'order_by' in request.json.keys():
        # 前端要这样传 "order_by":[ {"key": "auth_user.id","desc": true}, ]
        order_by = request.json['order_by']

    if 'username' in request.json.keys():
        filters_list.append(value_like_filter(AuthUser.username, request.json['username']))

    if 'role_id' in request.json.keys():
        filters_list.append(AuthUser.role_id == request.json['role_id'])

    if 'group_id' in request.json.keys():
        use_group_filter = True
        filters_list.append(AuthGroup.id == request.json['group_id'])
    # 该过滤条件是针对只要用户属于group_id_list里面的任意一个组,那么就能将该用户过滤出来
    if 'group_id_list' in request.json.keys():
        use_group_filter = True
        filters_list.append(in_list_filter(AuthGroup.id, request.json['group_id_list']))
    # 该过滤条件针对的是,用户必须要同时具有group_id_all_in_list里面的所有组,该用户才能被过滤出来
    if 'group_id_all_in_list' in request.json.keys():
        # 如果请求中包含group_id_all_in_list参数
        use_group_all_in_filter = True
        group_id_all_in_list = request.json['group_id_all_in_list']

    order_by = generate_orderby_text(order_by)

    if use_group_filter:
        query: BaseQuery = db.session.query(AuthUser, AuthRole) \
            .select_from(AuthUser) \
            .outerjoin(AuthRole, AuthUser.role_id == AuthRole.id) \
            .outerjoin(RsAuthUserGroup, AuthUser.id == RsAuthUserGroup.user_id) \
            .outerjoin(AuthGroup, RsAuthUserGroup.group_id == AuthGroup.id) \
            .filter(*filters_list) \
            .order_by(order_by)

    elif use_group_all_in_filter:
        # 找出同时在所有指定组的用户的 ID
        subquery = db.session.query(RsAuthUserGroup.user_id) \
            .filter(RsAuthUserGroup.group_id.in_(group_id_all_in_list)) \
            .group_by(RsAuthUserGroup.user_id) \
            .having(
            func.count(RsAuthUserGroup.group_id.in_(group_id_all_in_list)) == len(group_id_all_in_list)
        )
        # RsAuthUserGroup.group_id.in_(group_id_all_in_list) 这个语句返回的是0或者1,符合条件就是1
        # 对关系表的用户id分组后,再用having过滤,并且过滤条件里面用聚合函数count进行计数,统计符合条件的行数

        # 使用子查询找出用户对象
        query = db.session.query(AuthUser, AuthRole) \
            .select_from(AuthUser) \
            .outerjoin(AuthRole, AuthUser.role_id == AuthRole.id) \
            .filter(AuthUser.id.in_(subquery))
    else:
        query: BaseQuery = db.session.query(AuthUser, AuthRole) \
            .select_from(AuthUser) \
            .outerjoin(AuthRole, AuthUser.role_id == AuthRole.id) \
            .filter(*filters_list) \
            .order_by(order_by)

    pagination, records = get_pagination_record_from_request_and_query(request, query, 1, 10)

    records: List[Tuple[AuthUser, AuthRole]]

    user_info_in_list = list()

    for i in records:
        user, role = i
        user_info_in_list.append(formatter_account_info(user, role))

    return jsonify_return_body(
        body_key_list=['code', 'msg', 'data'],
        result=True,
        data=user_info_in_list,
        pagination=pagination
    )


.
.
.

posted @   tengyifan  阅读(154)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示