FastAPI 进阶三部曲:中间件、依赖注入与 ORM 实战
一、引言FastAPI 作为当前 Python 领域最炙手可热的异步 Web 框架凭借其高性能、自动生成 API 文档以及对异步的原生支持赢得了大量开发者的青睐。然而仅仅掌握路由和请求响应的基础用法远不足以构建一个健壮的企业级应用。中间件Middleware、依赖注入Dependency Injection和ORM对象关系映射正是进阶路上必须跨越的三座大山。本文将基于 FastAPI 官方最佳实践结合 SQLAlchemy 2.0 异步特性从零搭建一个完整的图书管理 API涵盖统一日志处理、用户认证依赖、以及完整的数据库增删改查、分页、聚合查询等核心功能。所有代码均可在实际项目中直接复用。二、中间件Middleware—— 为所有请求添加“守门员”2.1 什么是中间件中间件是一个在每次请求进入 FastAPI 应用时都会被执行的函数。它在请求到达路径操作函数之前运行并且在响应返回给客户端之前再执行一次。你可以把它想象成一个“守门员”对所有进出请求进行统一处理。2.2 中间件的典型应用场景记录每个请求的耗时和日志统一身份认证虽然更推荐用依赖注入但中间件也可做全局鉴权跨域资源共享CORS配置统一添加或修改响应头如X-Request-ID性能监控和指标收集2.3 如何定义一个中间件使用app.middleware(http)装饰器函数签名为async def middleware(request: Request, call_next)。内部通过await call_next(request)调用下一个中间件或最终的路由处理函数并获取响应对象。from fastapi import FastAPI, Request import time app FastAPI() app.middleware(http) async def log_requests(request: Request, call_next): # 请求前处理 start_time time.time() print(f收到请求: {request.method} {request.url.path}) # 执行后续逻辑路由处理函数或下一个中间件 response await call_next(request) # 响应后处理 process_time time.time() - start_time response.headers[X-Process-Time] str(process_time) print(f请求处理完成耗时: {process_time:.4f}秒) return response2.4 多个中间件的执行顺序顺序是“自下而上”—— 即先注册的后执行类似洋葱模型。例如app.middleware(http) async def middleware_a(request, call_next): print(A 开始) response await call_next(request) print(A 结束) return response app.middleware(http) async def middleware_b(request, call_next): print(B 开始) response await call_next(request) print(B 结束) return response2.4.1核心结论FastAPI 中后注册的中间件会先执行前置逻辑收尾逻辑则逆序执行。 你代码里先定义middleware_a、再定义middleware_b注册顺序A→B执行打印顺序B 开始 A 开始 # 路由接口业务逻辑执行 A 结束 B 结束2.4.2 原理说明FastAPI 会把多个 HTTP 中间件层层嵌套包装B(middleware_a(路由函数))调用call_next(request)就是进入内层中间件 / 路由先走外层 B 前置B 开始进入内层 A 前置A 开始走到真正接口视图函数接口返回后先退出 A 后置A 结束最后退出 B 后置B 结束2.4.3 直观流程图请求进来 ↓ middleware_b 【前置】打印 B 开始 ↓ call_next() middleware_a 【前置】打印 A 开始 ↓ call_next() 路由处理函数执行业务 ↑ 响应返回 middleware_a 【后置】打印 A 结束 ↑ 回到上一层 middleware_b 【后置】打印 B 结束 ↓ 返回响应给客户端三、依赖注入Dependency Injection—— 告别重复代码3.1 依赖注入系统的作用依赖注入是一种设计模式FastAPI 内置了极其优雅的实现。它的核心思想是将可复用的逻辑如数据库会话、用户身份校验、配置对象抽取为依赖项由框架自动调用并注入到路径操作函数中。主要优势代码复用一次编写多处使用解耦业务逻辑与基础设施数据库、缓存等分离易于测试可以轻松用模拟对象替换真实依赖进行单元测试3.2 使用步骤创建一个可调用对象函数或类作为依赖项在路径操作函数参数中使用Depends(依赖项)声明FastAPI 自动解析并注入依赖项的结果3.3 实战用户认证依赖项假设我们有多个接口需要验证 JWT Token并返回当前用户信息。from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt oauth2_scheme OAuth2PasswordBearer(tokenUrltoken) # 模拟用户数据 fake_users_db { admin: {username: admin, role: superadmin} } async def get_current_user(token: str Depends(oauth2_scheme)): credentials_exception HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detail无效的认证凭据, headers{WWW-Authenticate: Bearer}, ) try: payload jwt.decode(token, SECRET_KEY, algorithms[HS256]) username: str payload.get(sub) if username is None: raise credentials_exception except JWTError: raise credentials_exception user fake_users_db.get(username) if user is None: raise credentials_exception return user # 在路由中使用 app.get(/users/me) async def read_users_me(current_user: dict Depends(get_current_user)): return current_user这样一来所有需要认证的接口只需声明current_user Depends(get_current_user)即可完全避免了在每个函数里重复编写解析 Token 的代码。四、ORM对象关系映射—— 用面向对象的方式操作数据库4.1 ORM 简介ORM 将数据库表映射为 Python 类将表中的行映射为类的实例对象。开发者通过操作对象和方法即可完成增删改查无需手写 SQL。在 FastAPI 异步生态中SQLAlchemy 2.0是绝对的首选它原生支持async/await性能强大企业应用广泛。ORM 带来的好处减少重复的 SQL 拼接代码代码更简洁、可读性更强自动管理数据库连接和事务有效防止 SQL 注入攻击4.2 环境准备与引擎创建首先安装依赖pip install fastapi uvicorn sqlalchemy[asyncio] aiomysql创建异步数据库引擎以 MySQL 为例from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker, declarative_base from sqlalchemy import Column, Integer, String, DateTime, func from datetime import datetime ASYNC_DATABASE_URL mysqlaiomysql://root:123456localhost:3306/fastapi_test?charsetutf8 async_engine create_async_engine( ASYNC_DATABASE_URL, echoTrue, # 打印 SQL 日志便于调试 pool_size10, # 连接池保持的持久连接数 max_overflow20 # 允许额外创建的连接数 ) AsyncSessionLocal sessionmaker( async_engine, class_AsyncSession, expire_on_commitFalse )4.3 定义模型基类和模型类我们定义一个基类包含所有表共有的create_time和update_time字段然后为图书表创建模型。from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy import String, DateTime, func class Base(DeclarativeBase): create_time: Mapped[datetime] mapped_column( DateTime, insert_defaultfunc.now(), defaultdatetime.now, comment创建时间 ) update_time: Mapped[datetime] mapped_column( DateTime, insert_defaultfunc.now(), onupdatefunc.now(), defaultdatetime.now, comment修改时间 ) class Book(Base): __tablename__ book id: Mapped[int] mapped_column(primary_keyTrue, autoincrementTrue) bookname: Mapped[str] mapped_column(String(255), nullableFalse) author: Mapped[str] mapped_column(String(255), nullableFalse) price: Mapped[float] mapped_column(nullableTrue) # 价格字段为后续查询演示扩展4.4 创建数据库表应用启动时利用 FastAPI 的startup事件在应用启动时自动建表。async def create_tables(): async with async_engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) app.on_event(startup) async def startup_event(): await create_tables()4.5 获取数据库会话的依赖项每次请求需要独立的事务会话我们将其封装为依赖项并自动管理会话的关闭。4.5.1异步会话工厂 AsyncSessionLocalAsyncSessionLocal async_sessionmaker( bindasync_engine, # 绑定全局异步数据库引擎提前初始化的async数据库连接引擎 class_AsyncSession, # 指定使用SQLAlchemy异步会话类AsyncSession expire_on_commitFalse # commit之后模型对象不会过期不用重复查库方便查询后继续使用ORM对象 )async_sessionmakerSQLAlchemy 异步版会话工厂用来批量创建数据库会话expire_on_commitFalse常用场景查询拿到数据 commit 后依然能正常读取模型属性不会报lazy loading过期报错4.5.2依赖函数 get_database最关键这是 FastAPI 依赖项每来一次 HTTP 请求就执行一次生成全新独立 sessionasync def get_database(): async with AsyncSessionLocal() as session: try: yield session # 把会话给到接口函数使用yield实现依赖的上下文暂停 await session.commit() # 接口无报错自动提交事务 except Exception: await session.rollback() # 接口抛异常事务回滚保证数据一致性 raise # 重新抛出异常让FastAPI正常返回错误响应 finally: await session.close() # 无论成功失败最终强制关闭会话释放连接4.5.3路由层Depends 注入使用app.get(/book/books) async def get_book_list( db: AsyncSession Depends(get_database) ): # 使用注入进来的db会话执行查询 result await db.execute(select(Book)) book_list result.scalars().all() return book_list五、路由中使用 ORM 与数据库操作5.1 依赖注入数据库会话核心创建依赖项get_database返回异步数据库会话AsyncSession并通过Depends注入到路由处理函数。from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker # 创建异步会话工厂 AsyncSessionLocal async_sessionmaker(async_engine, expire_on_commitFalse) async def get_database() - AsyncSession: async with AsyncSessionLocal() as session: yield session在路由中from fastapi import Depends, FastAPI from sqlalchemy.ext.asyncio import AsyncSession app FastAPI() app.get(/books) async def get_books(db: AsyncSession Depends(get_database)): # 使用 db 执行查询 pass5.2 查询操作5.2.1 查询所有数据与单条数据查询所有select(模型类)→db.execute()→scalars().all()from sqlalchemy import select app.get(/book/get_books) async def get_book_list(db: AsyncSession Depends(get_database)): result await db.execute(select(Book)) books result.scalars().all() return books查询单条使用scalars().first()或db.get(模型类, 主键值)app.get(/book/get_book) async def get_book(db: AsyncSession Depends(get_database)): # 方式一提取第一条 # result await db.execute(select(Book)) # book result.scalars().first() # 方式二通过主键获取 book await db.get(Book, 1) return book5.2.2 查询条件在select().where()中添加条件支持多种比较和逻辑运算。比较判断,,,,app.get(/book/{book_id}) async def get_book_by_id(book_id: int, db: AsyncSession Depends(get_database)): result await db.execute(select(Book).where(Book.id book_id)) book result.scalar_one_or_none() return book模糊查询like()%匹配任意字符_匹配单个字符app.get(/book/get_books_by_author) async def get_books_by_author(db: AsyncSession Depends(get_database)): result await db.execute(select(Book).where(Book.author.like(曹%))) books result.scalars().all() return books与非查询使用与、|或、~非app.get(/book/get_books_filter) async def get_books_filter(db: AsyncSession Depends(get_database)): result await db.execute( select(Book).where((Book.author 曹雪芹) (Book.price 200)) ) books result.scalars().all() return books包含查询in_()app.get(/book/get_books_by_ids) async def get_books_by_ids(db: AsyncSession Depends(get_database)): id_list [1, 2, 3, 4, 5, 6] result await db.execute(select(Book).where(Book.id.in_(id_list))) books result.scalars().all() return books5.2.3 聚合查询使用func.count(),func.avg(),func.max(),func.min(),func.sum()进行聚合。from sqlalchemy import func app.get(/book/count) async def get_count(db: AsyncSession Depends(get_database)): # result await db.execute(select(func.count(Book.id))) # result await db.execute(select(func.max(Book.price))) # result await db.execute(select(func.sum(Book.price))) result await db.execute(select(func.avg(Book.price))) count result.scalar() return count5.2.4 分页查询使用.offset().limit()实现分页。offset为跳过的记录数limit为每页返回的记录数。计算公式offset (当前页码 - 1) * 每页数量当前页码每页数量(limit)跳过数量(offset)1100210103102041030app.get(/book/get_books) async def get_book_list( page: int 1, page_size: int 3, db: AsyncSession Depends(get_database) ): skip (page - 1) * page_size stmt select(Book).offset(skip).limit(page_size) result await db.execute(stmt) books result.scalars().all() return {books: books}5.2.5 查询总结核心思路select()→db.execute()→ 从 ORM 对象获取数据 → 响应结果获取数据方式scalars().all()获取所有数据scalars().first()获取第一条数据scalar_one_or_none()获取一个或 None若多于一条则报错scalar()获取标量值聚合查询常用5.3 新增操作步骤创建 ORM 对象 →db.add()→await db.commit()from pydantic import BaseModel class BookBase(BaseModel): bookname: str author: str price: float app.post(/book/add_book) async def add_book(book: BookBase, db: AsyncSession Depends(get_database)): book_obj Book(**book.__dict__) # 或 Book(booknamebook.bookname, ...) db.add(book_obj) await db.commit() return book_obj5.4 更新操作步骤查询获取对象 → 修改属性 →commitclass BookUpdate(BaseModel): bookname: str author: str price: float app.put(/book/update_book/{book_id}) async def update_book( book_id: int, data: BookUpdate, db: AsyncSession Depends(get_database) ): book await db.get(Book, book_id) if book is None: raise HTTPException(status_code404, detailBook not found) book.bookname data.bookname book.author data.author book.price data.price await db.commit() return book5.5 删除操作步骤查询获取对象 →db.delete()→commitapp.delete(/book/delete_book/{book_id}) async def delete_book(book_id: int, db: AsyncSession Depends(get_database)): db_book await db.get(Book, book_id) if db_book is None: raise HTTPException(status_code404, detailBook not found) await db.delete(db_book) await db.commit() return {message: Book deleted}六、总结本文围绕 FastAPI 进阶的三大核心内容展开中间件为每个请求/响应添加统一处理逻辑定义简单执行顺序自下而上。依赖注入抽取可复用组件如数据库会话、认证逻辑实现解耦与易测性。ORMSQLAlchemy通过对象方式操作数据库避免手写 SQL提升开发效率与安全性。ORM 使用全流程速览安装依赖pip install sqlalchemy[asyncio] aiomysql创建异步引擎create_async_engine定义基类DeclarativeBase和模型类启动时建表run_sync(Base.metadata.create_all)路由中注入会话依赖Depends(get_database)执行 CRUDselect()、add()、属性赋值、delete()最后commit()掌握这些技能即可构建健壮、可维护的 FastAPI 企业级应用。

相关新闻

梁文锋20个技术关键词解析:云原生、微服务与AI编程实践指南

梁文锋20个技术关键词解析:云原生、微服务与AI编程实践指南

最近在技术圈里,一个现象级的分享正在被频繁讨论:梁文锋长达四小时的深度分享,被提炼成了20个关键词。这不仅仅是简单的会议记录,而是对当前技术发展趋势的一次系统性梳理。如果你正在思考下一步技术方向、团队建设或产品架构&…

2026/8/17 13:36:59 阅读更多 →
深度学习基础 Week5 分类算法基础知识

深度学习基础 Week5 分类算法基础知识

目录 摘要 Abstract 1学习概述 2机器学习分类任务简介 2.1核心定义 2.2分类任务核心类型 2.3分类模型核心分支 3分类与回归的核心区别 3.1核心本质差异 3.2具体实例对比 3.3建模与评价差异 4分类任务核心底层知识点总结 5学习总结与感悟 摘要 本文系统梳理了机器…

2026/8/21 5:15:23 阅读更多 →
TI Tiva™ LCD控制器实战:DMA帧缓冲、子画面与中断配置详解

TI Tiva™ LCD控制器实战:DMA帧缓冲、子画面与中断配置详解

1. 项目概述与核心价值 在嵌入式图形显示开发中,LCD控制器是连接微控制器与显示面板的桥梁,其性能直接决定了最终的视觉体验。很多开发者初次接触时,往往被手册中繁杂的寄存器、时序图和模式选项所困扰,配置过程如同“盲人摸象”&…

2026/8/22 0:46:30 阅读更多 →

最新新闻

Nginx核心知识点与面试高频问题解析

Nginx核心知识点与面试高频问题解析

1. Nginx面试核心知识点解析作为Web服务领域的瑞士军刀,Nginx在技术面试中的考察频率居高不下。根据我对数百场技术面试的观察统计,Nginx相关问题主要集中在配置优化、架构原理和故障排查三个维度。以下是面试官最常深挖的12个技术要点:1.1 基…

2026/8/22 6:18:26 阅读更多 →
铁路站台安全标线建模:从人体运动学到动态视觉引导

铁路站台安全标线建模:从人体运动学到动态视觉引导

1. 项目概述:一道真实赛题背后的工程思维落地2023年辽宁省大学数学建模竞赛A题——“铁路车站的安全标线”,表面看是个交通管理场景下的几何与优化问题,实则是一次对建模者“工程直觉数学表达现实约束”三重能力的综合检验。我带过七届校队&a…

2026/8/22 6:18:26 阅读更多 →
AI智能体如何通过合理推理避免博弈论陷阱:从纳什均衡到合作均衡

AI智能体如何通过合理推理避免博弈论陷阱:从纳什均衡到合作均衡

1. 项目概述:当AI智能体学会“讲道理”最近在AI智能体(AI agents)的研究圈里,一个挺有意思的话题被反复讨论:如果我们让智能体在互动中具备“合理推理”(Reasonably reasoning)的能力&#xff0…

2026/8/22 6:18:26 阅读更多 →
智能体AI集成异常检测:构建主动风险管理的感知决策闭环

智能体AI集成异常检测:构建主动风险管理的感知决策闭环

1. 项目概述:当智能体学会“预警”最近在跟几个做智能决策系统的朋友聊天,大家普遍遇到一个头疼的问题:系统运行得挺好,能处理任务,也能学习优化,但总感觉“缺根弦”。缺哪根弦呢?缺的是那种“未…

2026/8/22 6:18:26 阅读更多 →
WarcraftHelper:三步部署,修复魔兽争霸3宽屏、帧率锁定与8MB地图限制

WarcraftHelper:三步部署,修复魔兽争霸3宽屏、帧率锁定与8MB地图限制

WarcraftHelper:三步部署,修复魔兽争霸3宽屏、帧率锁定与8MB地图限制 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 在 1.27b…

2026/8/22 6:18:26 阅读更多 →
2023 Java面试核心知识点与实战指南

2023 Java面试核心知识点与实战指南

1. Java面试核心知识点梳理2023年Java技术栈的面试难度明显提升,各大厂对候选人的要求从单纯的八股文背诵转向了深度原理理解和实战能力考察。根据我最近三个月参与的技术面试和行业交流,整理出这份覆盖90%高频考点的备战指南。Java面试的核心考察点主要…

2026/8/22 6:17:26 阅读更多 →

日新闻

沉金PCB工艺实战指南:从设计到SMT焊接的可靠性保障

沉金PCB工艺实战指南:从设计到SMT焊接的可靠性保障

在电子硬件开发领域,PCB(印制电路板)的沉金工艺是提升产品可靠性和焊接质量的关键环节。对于需要高密度互连、长期稳定运行或高频信号传输的板卡,如“黍姐仿通行证”这类可能涉及身份识别、数据交互的硬件项目,选择正确…

2026/8/22 0:00:11 阅读更多 →
电气考研电路八月强化四步法:从知识体系到真题实战的闭环攻略

电气考研电路八月强化四步法:从知识体系到真题实战的闭环攻略

这次我们来看一个针对电气考研电路科目的学习规划项目。它不是软件工具,而是一套聚焦于8月份关键节点的备考策略。对于电气工程考研的同学来说,电路分析是专业课的重中之重,也是拉开分差的关键。进入8月,复习进入强化阶段&#xf…

2026/8/22 0:00:11 阅读更多 →
消除AI代码的“AI味”:Claude Code设计优化技能配置与实战指南

消除AI代码的“AI味”:Claude Code设计优化技能配置与实战指南

大家好,我是专注于前端开发与AI工具实践的技术博主。在日常使用 Claude Code 等AI编程助手时,你是否也遇到过这样的困扰:生成的代码功能上没问题,但代码风格、组件设计、交互逻辑总透着一股“AI味”——布局单调、样式简陋、交互生…

2026/8/22 0:00:11 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/21 3:21:33 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/21 0:02:09 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/21 6:07:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/21 16:42:28 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/20 21:46:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →