FastAPI 与 SQLModel 分页功能实现指南

FastAPI 与 SQLModel 分页功能实现指南

1. 基础分页模型

from typing import Generic, TypeVar, Optional, List
from pydantic import BaseModel
from sqlmodel import SQLModelT = TypeVar("T")class PageParams(BaseModel):page: int = 1size: int = 10class PageResponse(SQLModel, Generic[T]):items: List[T]total: intpage: intsize: intpages: inthas_next: boolhas_prev: bool@propertydef next_page(self) -> Optional[int]:if self.has_next:return self.page + 1return None@propertydef prev_page(self) -> Optional[int]:if self.has_prev:return self.page - 1return None

2. 通用分页函数

2.1 基础分页查询

from sqlmodel import select, Session, funcdef paginate_query(session: Session,query,page: int = 1,size: int = 10
) -> PageResponse:# 计算总数total = session.exec(select(func.count()).select_from(query.subquery())).one()# 计算总页数pages = (total + size - 1) // size# 应用分页items = session.exec(query.offset((page - 1) * size).limit(size)).all()return PageResponse(items=items,total=total,page=page,size=size,pages=pages,has_next=page < pages,has_prev=page > 1)

2.2 带过滤和排序的分页查询

from typing import Optional, List
from sqlalchemy import desc, ascdef get_users_paginated(session: Session,page: int = 1,size: int = 10,search: Optional[str] = None,sort_by: Optional[str] = None,sort_order: str = "asc"
) -> PageResponse[User]:query = select(User)# 添加搜索条件if search:query = query.where(User.username.ilike(f"%{search}%") |User.email.ilike(f"%{search}%"))# 添加排序if sort_by:direction = asc if sort_order == "asc" else descquery = query.order_by(direction(getattr(User, sort_by)))return paginate_query(session, query, page, size)

3. FastAPI 路由实现

3.1 基础分页路由

from fastapi import APIRouter, Depends, Query
from sqlmodel import Sessionrouter = APIRouter()@router.get("/users", response_model=PageResponse[User])
def get_users(page: int = Query(1, ge=1),size: int = Query(10, ge=1, le=100),session: Session = Depends(get_session)
):query = select(User)return paginate_query(session, query, page, size)

3.2 高级分页路由

@router.get("/users/advanced", response_model=PageResponse[User])
def get_users_advanced(page: int = Query(1, ge=1),size: int = Query(10, ge=1, le=100),search: Optional[str] = Query(None),sort_by: Optional[str] = Query(None),sort_order: str = Query("asc", regex="^(asc|desc)$"),session: Session = Depends(get_session)
):return get_users_paginated(session=session,page=page,size=size,search=search,sort_by=sort_by,sort_order=sort_order)

4. 前端分页实现

4.1 使用 Axios 调用分页 API

interface PaginationParams {page: number;size: number;search?: string;sortBy?: string;sortOrder?: 'asc' | 'desc';
}async function fetchUsers(params: PaginationParams) {const { page, size, search, sortBy, sortOrder } = params;const response = await axios.get('/api/users/advanced', {params: {page,size,search,sort_by: sortBy,sort_order: sortOrder}});return response.data;
}

4.2 Vue 3 分页组件

<template><div class="pagination"><!-- 数据展示 --><div class="items"><div v-for="item in pageData.items" :key="item.id">{{ item.username }}</div></div><!-- 分页控制 --><div class="controls"><button :disabled="!pageData.has_prev"@click="changePage(pageData.prev_page)">上一页</button><span>{{ pageData.page }} / {{ pageData.pages }}</span><button :disabled="!pageData.has_next"@click="changePage(pageData.next_page)">下一页</button></div></div>
</template><script setup lang="ts">
import { ref, onMounted } from 'vue';const pageData = ref({items: [],total: 0,page: 1,size: 10,pages: 0,has_next: false,has_prev: false
});const loading = ref(false);async function loadData(page = 1) {loading.value = true;try {const data = await fetchUsers({page,size: 10});pageData.value = data;} catch (error) {console.error('Failed to load data:', error);} finally {loading.value = false;}
}function changePage(newPage: number) {if (newPage) {loadData(newPage);}
}onMounted(() => {loadData();
});
</script><style scoped>
.pagination {display: flex;flex-direction: column;gap: 1rem;
}.controls {display: flex;justify-content: center;gap: 1rem;align-items: center;
}button:disabled {opacity: 0.5;cursor: not-allowed;
}
</style>

5. 性能优化建议

  1. 查询优化
    • 为分页字段添加索引
    • 使用 COUNT(*) OVER() 优化计数查询
    • 对大数据集使用游标分页
def optimize_count_query(session: Session, query):# 使用窗口函数优化计数count_query = query.add_columns(func.count().over().label("total"))first_result = session.exec(count_query).first()return first_result.total if first_result else 0
  1. 缓存策略
from functools import lru_cache@lru_cache(maxsize=100)
def get_cached_page(page: int, size: int, cache_key: str):return get_users_paginated(page=page, size=size)

6. 常见问题解决

6.1 处理空结果

def handle_empty_page(session: Session,query,page: int,size: int
) -> PageResponse:total = session.exec(select(func.count()).select_from(query.subquery())).one()if total == 0:return PageResponse(items=[],total=0,page=page,size=size,pages=0,has_next=False,has_prev=False)# 如果请求的页码超出范围,返回最后一页pages = (total + size - 1) // sizeif page > pages:return paginate_query(session, query, pages, size)return paginate_query(session, query, page, size)

6.2 处理无效参数

def validate_page_params(page: int, size: int) -> tuple[int, int]:"""验证并修正分页参数"""page = max(1, page)  # 页码最小为1size = max(1, min(size, 100))  # 每页大小在1-100之间return page, size

7. 测试分页功能

def test_pagination():# 创建测试数据users = [User(username=f"user{i}", email=f"user{i}@example.com") for i in range(25)]with Session(engine) as session:session.add_all(users)session.commit()# 测试基本分页page1 = paginate_query(session, select(User), page=1, size=10)assert len(page1.items) == 10assert page1.total == 25assert page1.has_next is True# 测试最后一页page3 = paginate_query(session, select(User), page=3, size=10)assert len(page3.items) == 5assert page3.has_next is False

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/495628.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RK3506开发板:智能硬件领域的新选择,带来卓越性能与低功耗

在现代智能硬件开发中&#xff0c;选择一款性能稳定、功耗低的开发板是确保产品成功的关键。Rockchip最新推出的RK3506芯片&#xff0c;凭借其卓越的能效比、多功能扩展性和优秀的实时性能&#xff0c;已经成为智能家电、工业控制、手持终端等领域的热门选择。而基于RK3506的Ar…

【AIGC-ChatGPT进阶副业提示词】星际占卜师:探索星象能量的艺术【限时免费阅读,一天之后自动进入进阶课程】

引言 在这个数字化的时代&#xff0c;我们创造了一个独特的角色 —— 星际占卜师。这不仅是一个简单的运势预测工具&#xff0c;更是一个融合了玄学、预言和能量解读的智能向导。通过精心设计的系统提示词和独特的画境生成机制&#xff0c;星际占卜师能够为用户带来沉浸式的占…

机器学习之PCA降维

主成分分析&#xff08;PCA&#xff0c;Principal Component Analysis&#xff09; 主成分分析&#xff08;PCA&#xff09;是一种常见的无监督学习技术&#xff0c;广泛应用于数据降维、数据可视化以及特征提取等任务。PCA的目标是通过线性变换将数据从高维空间映射到低维空间…

SOTA简繁中文拼写检查工具:FASPell Chinese Spell Checker 论文

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

Visual Studio Code历史版本下载

本章教程&#xff0c;介绍如何找到Visual Studio Code的历史版本官方下载地址。 一、历史版本下载地址 下载地址&#xff1a;https://code.visualstudio.com/updates/ 二、常用版本下载地址 August 2017 (version 1.16)&#xff1a;https://code.visualstudio.com/updates/v1_…

Kubernetes(k8s)离线部署DolphinScheduler3.2.2

1.环境准备 1.1 集群规划 本次安装环境为&#xff1a;3台k8s现有的postgreSql数据库zookeeper服务 1.2 下载及介绍 DolphinScheduler-3.2.2官网&#xff1a;https://dolphinscheduler.apache.org/zh-cn/docs/3.2.2 官网安装文档&#xff1a;https://dolphinscheduler.apach…

【自动化测试】windows下安装Selenium浏览器界面测试工具

Date: 2024.12.23 10:15:53 author: lijianzhan 简述&#xff1a;这篇教程详细介绍了如何在Windows环境下安装selenium&#xff0c;并设置Chrome浏览器驱动。什么是Selenium&#xff1f;Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供了一种跨平台、跨浏览器的端…

如何在 Ubuntu 22.04 上安装 phpMyAdmin

简介 PHPMyAdmin 是在 Ubuntu 22.04 上管理 MySQL 数据库的绝佳选择。它是一个流行的工具&#xff0c;拥有简单、高效且用户友好的基于 Web 的界面&#xff0c;让你能够轻松地管理 MySQL 数据库。因此&#xff0c;许多开发人员、数据库管理员和网站所有者都信任 PHPMyAdmin 来…

大数据-256 离线数仓 - Atlas 数据仓库元数据管理 正式安装 启动服务访问 Hive血缘关系导入

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

[Python3] Sanic中间件

在 Sanic 中&#xff0c;中间件&#xff08;middleware&#xff09;是指在请求和响应之间执行的代码。它们是一个非常强大的工具&#xff0c;用于处理请求的预处理、响应的后处理、全局错误处理、日志记录、认证、权限校验、跨域资源共享&#xff08;CORS&#xff09;等任务。中…

使用 OpenCV 绘制线条和矩形

OpenCV 是一个功能强大的计算机视觉库&#xff0c;它不仅提供了丰富的图像处理功能&#xff0c;还支持图像的绘制。绘制简单的几何图形&#xff08;如线条和矩形&#xff09;是 OpenCV 中常见的操作。在本篇文章中&#xff0c;我们将介绍如何使用 OpenCV 在图像上绘制线条和矩形…

操作系统课程设计

摘 要 本项目旨在深入设计与实现一套基于Java的模拟操作系统&#xff0c;模拟和实现常见操作系统的核心功能&#xff0c;包括进程管理、内存分配与调度、高效的文件系统和多样化设备的管理。通过该模拟操作系统的开发&#xff0c;探索计算机操作系统的基础理论与实际工程细节…

css改变输入右下角图标

前言 正常情况下&#xff0c;HTML textarea 多行文本输入框会存如下图所示图标&#xff0c; 用户可拉动它改变高度&#xff0c;这是我们不想看到的&#xff0c;所以要去掉它。 去掉后&#xff1a; 解决方案 设置 resize 属性即可&#xff0c;如下代码所示&#xff1a; <…

HTML-CSS(day01)

W3C标准&#xff1a; W3C&#xff08; World Wide Web Consortium&#xff0c;万维网联盟&#xff09; W3C是万维网联盟&#xff0c;这个组成是用来定义标准的。他们规定了一个网页是由三部分组成&#xff0c;分别是&#xff1a; 三个组成部分&#xff1a;&#xff08;1&…

2024-12-24 NO1. XR Interaction ToolKit 环境配置

文章目录 1 软件配置2 安装 XRToolKit3 配置 OpenXR4 安装示例场景5 运行测试 1 软件配置 Unity 版本&#xff1a;Unity6000.0.26 ​ 2 安装 XRToolKit 创建新项目&#xff08;URP 3D&#xff09;&#xff0c;点击进入 Asset Store。 进入“Unity Registry”页签&#xff0…

C语言基础——指针(4)

一&#xff0e; 字符指针变量 字符指针变量的使用和整型指针变量的使用方法相似&#xff0c;以下是其基本使用方法的例子&#xff1a; &#xff08;1&#xff09;字符指针变量还有一种使用方法&#xff1a; const char* p "abcd" 需…

week 11 - BCNF

1. More on functional dependencies (功能依赖的更多内容) Lossless decomposition (无损分解) 研究如何在分解表的过程中不丢失信息&#xff0c;也就是说&#xff0c;通过分解后的表可以无损地重建原始表。 2. BCNF (Boyce-Codd Normal Form, BCNF范式) &#xff08;1&…

嵌入式学习-QT-Day06

嵌入式学习-QT-Day06 六、多窗口编程 1、QMessageBox 消息对话框 2、QWidget类 3、parent参数 4、堆栈窗口&#xff08;QStackedWidget&#xff09; 5、新建自定义窗口类 6、对象传值 6.1 父对象 → 子对象 6.2 子对象 → 父对象 7、事件机制 8、QMainWindow主窗口类 8.1 QMenu…

《战神:诸神黄昏》游戏运行时提示找不到gamede.dll文件怎么办?gamede.dll丢失的修复指南

在沉浸于《战神&#xff1a;诸神黄昏》的壮阔世界时&#xff0c;突然弹出的“找不到gamede.dll文件”错误提示可能会让玩家措手不及。作为一名经验丰富的软件开发从业者&#xff0c;我深知这类问题对游戏体验的影响。今天&#xff0c;我将为大家详细解析gamede.dll文件丢失的原…

1.系统学习-线性回归

系统学习-线性回归 前言线性回归介绍误差函数梯度下降梯度下降示例 回归问题常见的评价函数1. MAE, mean absolutely error2. MSE, mean squared error3. R square &#xff08;决定系数或R方&#xff09; 机器学习建模流程模型正则化拓展阅读作业 链接: 2.系统学习-逻辑回归 …