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
)
.
.
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· 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