SQLAlchemy通用分页函数实现:支持搜索、排序和动态页码导航

在Web应用开发中,分页功能是一个非常常见的需求。本文将介绍一个基于SQLAlchemy的通用分页函数实现,该实现不仅支持基本的分页功能,还包含了搜索、排序以及动态页码导航等高级特性。

功能特点

  1. 基本分页功能(页码、每页数量)
  2. 灵活的排序支持(单字段/多字段,升序/降序)
  3. 关键词搜索(支持多字段模糊搜索)
  4. 动态页码导航(可配置显示页码数量)
  5. 丰富的分页信息(包含前后页、首末页等导航信息)

代码实现

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)

返回数据结构

函数返回一个包含两个主要部分的字典:

  1. items: 当前页的数据列表
  2. 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应用场景中使用。通过合理的参数设计和返回值结构,使得前端可以轻松实现各种分页导航界面。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐