SQLAlchemy通用分页函数实现:支持搜索、排序和动态页码导航
SQLAlchemy通用分页函数实现:支持搜索、排序和动态页码导航
在Web应用开发中,分页功能是一个非常常见的需求。本文将介绍一个基于SQLAlchemy的通用分页函数实现,该实现不仅支持基本的分页功能,还包含了搜索、排序以及动态页码导航等高级特性。
功能特点
- 基本分页功能(页码、每页数量)
- 灵活的排序支持(单字段/多字段,升序/降序)
- 关键词搜索(支持多字段模糊搜索)
- 动态页码导航(可配置显示页码数量)
- 丰富的分页信息(包含前后页、首末页等导航信息)
代码实现
from typing import Dict, Any, Sequence, TypeVar, Optional, Union
from sqlalchemy.orm import Query
from sqlalchemy import func, desc, asc, or_
T = TypeVar('T')
def paginate(
query: Query,
page: int = 1,
per_page: int = 10,
show_pages: int = 7,
sort_by: Optional[Union[str, Sequence[str]]] = None,
sort_desc: bool = True,
search_query: Optional[str] = None,
search_fields: Optional[Sequence[str]] = None
) -> Dict[str, Any]:
"""
通用分页函数
Args:
query: SQLAlchemy查询对象
page: 当前页码
per_page: 每页显示数量
show_pages: 显示的页码数量
sort_by: 排序字段,可以是字符串或字符串序列
sort_desc: 是否降序排序,True为降序,False为升序
search_query: 搜索关键词
search_fields: 要搜索的字段列表
Returns:
包含分页数据和分页信息的字典
"""
# ... 具体实现代码 ...
核心功能解析
1. 搜索功能
函数支持多字段模糊搜索,通过ilike
操作符实现:
if search_query and search_fields:
model_class = query.column_descriptions[0]['entity']
search_conditions = []
for field in search_fields:
field_obj = getattr(model_class, field)
search_conditions.append(field_obj.ilike(f"%{search_query}%"))
if search_conditions:
query = query.filter(or_(*search_conditions))
2. 排序功能
支持单字段和多字段排序,可以指定升序或降序:
if sort_by:
if isinstance(sort_by, str):
sort_by = [sort_by]
for field in sort_by:
model_class = query.column_descriptions[0]['entity']
sort_field = getattr(model_class, field)
query = query.order_by(desc(sort_field) if sort_desc else asc(sort_field))
3. 动态页码导航
实现了动态页码范围计算,提供更好的用户体验:
half_show = show_pages // 2
if total_pages <= show_pages:
page_range = range(1, total_pages + 1)
else:
start_page = max(1, page - half_show)
end_page = min(total_pages, start_page + show_pages - 1)
if end_page - start_page < show_pages - 1:
start_page = max(1, end_page - show_pages + 1)
page_range = range(start_page, end_page + 1)
返回数据结构
函数返回一个包含两个主要部分的字典:
items
: 当前页的数据列表pagination
: 分页信息对象,包含:- current_page: 当前页码
- total_pages: 总页数
- total: 总记录数
- per_page: 每页显示数量
- has_prev: 是否有上一页
- has_next: 是否有下一页
- page_range: 显示的页码范围
- show_first: 是否显示首页
- show_last: 是否显示末页
- first_page: 首页页码
- last_page: 末页页码
使用示例
# 基本分页查询
result = paginate(
query=db.query(User),
page=1,
per_page=10
)
# 带搜索和排序的分页查询
result = paginate(
query=db.query(User),
page=1,
per_page=10,
search_query="john",
search_fields=["username", "email"],
sort_by="created_at",
sort_desc=True
)
总结
这个分页函数实现了一个功能完整、灵活可配置的分页解决方案。它不仅满足了基本的分页需求,还提供了搜索、排序等高级功能,可以在各种Web应用场景中使用。通过合理的参数设计和返回值结构,使得前端可以轻松实现各种分页导航界面。