FastAPI 进阶:中间件、依赖注入与 ORM

FastAPI 进阶:中间件、依赖注入与 ORM

目录

一、中间件(Middleware)

什么是中间件?

中间件的作用

如何定义中间件

多个中间件的执行顺序

二、依赖注入(Dependency Injection)

为什么需要依赖注入?

什么是依赖注入?

依赖注入的优势

依赖注入的应用场景

如何使用依赖注入

中间件 vs 依赖注入

三、ORM(对象关系映射)

什么是 ORM?

ORM 的优势

常见 ORM 工具

ORM 使用流程

实战示例

1. 创建数据库引擎

2. 定义模型类

3. 创建数据库表

4. 在路由中使用 ORM

总结

FastAPI 作为 Python Web 框架,提供了强大的功能来构建高性能、易维护的 API 应用。

一、中间件(Middleware)

什么是中间件?

中间件是在每次请求进入 FastAPI 应用时都会被执行的函数。它在请求到达实际的路由处理函数之前运行,并且在响应返回给客户端之前再运行一次。

中间件的作用

中间件可以为每个请求添加统一的处理逻辑,常见应用场景包括:

  • ✅ 性能监控
  • ✅ 日志记录
  • ✅ 身份认证
  • ✅ 响应头处理
  • ✅ 跨域处理

如何定义中间件

在函数顶部使用装饰器 @app.middleware("http")

@app.middleware("http") async def middleware(request, call_next): print('中间件开始处理 -- start') response = await call_next(request) print('中间件处理完成 -- end') return response

多个中间件的执行顺序

多个中间件的执行顺序是自下而上的:

客户端 → 中间件 B → 中间件 A → 路由处理函数 → 中间件 A → 中间件 B → 客户端

二、依赖注入(Dependency Injection)

为什么需要依赖注入?

在开发过程中,我们经常会遇到多个接口需要相同参数或逻辑的情况:

@app.get('/news/news_list') async def get_news_list( skip: int = Query(0, ge=0), limit: int = Query(10, le=60) ): return {"list": "新闻列表"} @app.get("/users/user_list") async def get_user_list( skip: int = Query(0, ge=0), limit: int = Query(10, le=60) ): return {"users": "用户列表"}

这种重复代码不仅冗余,也难以维护。依赖注入系统就是用来解决这个问题的。

什么是依赖注入?

  • 依赖项:可重用的组件(函数/类),负责提供某种功能或数据
  • 注入:FastAPI 自动帮你调用依赖项,并将结果"注入"到路径操作函数中

依赖注入的优势

  1. 代码复用:一次编写,多处使用
  2. 解耦:业务逻辑与基础设施代码分离
  3. 易于测试:轻松地用模拟依赖替换真实依赖进行测试

依赖注入的应用场景

  • 从请求中提取和验证参数
  • 管理数据库会话的创建、使用、关闭
  • 抽取封装多个路由公用的逻辑代码
  • 验证用户身份、检查权限和角色要求等

如何使用依赖注入

步骤 1:创建依赖项

async def common_parameters( skip: int = Query(0, ge=0), limit: int = Query(10, le=60) ): return { "skip": skip, "limit": limit }

步骤 2:导入并使用 Depends

from fastapi import Depends @app.get("/news/news_list") async def get_news_list( commons = Depends(common_parameters) ): return commons

中间件 vs 依赖注入

特性

中间件

依赖注入

控制范围

所有人(所有请求)

我说了算(可选择性使用)

适用场景

全局统一处理

部分路由共享逻辑

三、ORM(对象关系映射)

什么是 ORM?

ORM(Object-Relational Mapping,对象关系映射)是一种编程技术,用于在面向对象编程语言和关系型数据库之间建立映射。它允许开发者通过操作对象的方式与数据库进行交互,而无需直接编写复杂的 SQL 语句。

ORM 的优势

  • ✅ 减少重复的 SQL 代码
  • ✅ 代码更简洁易读
  • ✅ 自动处理数据库连接和事务
  • ✅ 自动防止 SQL 注入攻击

常见 ORM 工具

排名

ORM 工具

特点

适应场景

1

SQLAlchemy ORM

功能最强、最灵活、企业级

各类 API、微服务、数据应用

2

Django ORM

封装好、上手快

Django 项目、管理后台

3

Tortoise ORM

全异步

异步 Web 服务、高并发 API

ORM 使用流程

  1. 安装依赖
    • sqlalchemy[asyncio]
    • aiomysql(异步数据库驱动)
  1. 建库、建表
    • run_sync(Base.metadata.create_all)
  1. 操作数据
    • 查询
    • 新增
    • 修改
    • 删除

实战示例

1. 创建数据库引擎
from sqlalchemy.ext.asyncio import create_async_engine ASYNC_DATABASE_URL = "mysql+aiomysql://root:123456@localhost:3306/fastapi_test?charset=utf8" async_engine = create_async_engine( ASYNC_DATABASE_URL, echo=True, pool_size=10, max_overflow=20 )
2. 定义模型类
from sqlalchemy.ext.declarative import DeclarativeBase from sqlalchemy.orm import mapped_column, Mapped from sqlalchemy import DateTime, String, func from datetime import datetime class Base(DeclarativeBase): create_time: Mapped[datetime] = mapped_column( DateTime, insert_default=func.now(), default=datetime.now, comment="创建时间" ) update_time: Mapped[datetime] = mapped_column( DateTime, insert_default=func.now(), onupdate=func.now(), default=datetime.now, comment="修改时间" ) class User(Base): __tablename__ = "user" id: Mapped[int] = mapped_column(primary_key=True) username: Mapped[str] = mapped_column(String(255)) password: Mapped[str] = mapped_column(String(255))
3. 创建数据库表
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. 在路由中使用 ORM

创建异步会话工厂和依赖项:

from sqlalchemy.ext.asyncio import async_sessionmaker, AsyncSession AsyncSessionLocal = async_sessionmaker( bind=async_engine, class_=AsyncSession, expire_on_commit=False ) async def get_database(): async with AsyncSessionLocal() as session: try: yield session await session.commit() except Exception: await session.rollback() raise finally: await session.close()

查询数据:

from sqlalchemy import select @app.get("/users") async def get_user_list( db: AsyncSession = Depends(get_database) ): result = await db.execute(select(User)) users = result.scalars().all() return users

新增数据:

@app.post("/users") async def create_user( user: UserCreate, db: AsyncSession = Depends(get_database) ): db_user = User(username=user.username, password=user.password) db.add(db_user) await db.flush() return db_user

更新数据:

@app.put("/users/{user_id}") async def update_user( user_id: int, user_update: UserUpdate, db: AsyncSession = Depends(get_database) ): user = await db.get(User, user_id) if user: user.username = user_update.username user.password = user_update.password return user

删除数据:

@app.delete("/users/{user_id}") async def delete_user( user_id: int, db: AsyncSession = Depends(get_database) ): user = await db.get(User, user_id) if user: await db.delete(user) return {"message": "删除成功"}

总结

FastAPI 的这三个进阶特性各有所长:

  • 中间件:适合处理全局统一的请求/响应逻辑
  • 依赖注入:适合在部分路由间共享逻辑,灵活可控
  • ORM:让数据库操作变得面向对象,简洁安全

合理组合使用这三个特性,可以让你的 FastAPI 应用更加优雅、高效和易于维护!

Read more

NanoClaw 深度剖析:一个“AI 原生“架构的个人助手是如何运转的?

NanoClaw 深度剖析:一个“AI 原生“架构的个人助手是如何运转的?

你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益: 1. 了解大厂经验 2. 拥有和大厂相匹配的技术等 希望看什么,评论或者私信告诉我! 文章目录 * 一、它到底是什么?—— 三句话说清楚 * 二、整体架构:一张图看懂数据流 * 三、数据层:SQLite 才是"真相的唯一来源" * 3.1 为什么选 SQLite? * 3.2 游标机制:如何做到"断点续传" * 四、消息循环:一颗永不停跳的心脏 * 五、容器化执行:安全隔离的艺术 * 5.1 为什么要用容器? * 5.

By Ne0inhk
从「亡羊补牢」到「规则先行」:金仓数据库 SQL 防火墙实战解析

从「亡羊补牢」到「规则先行」:金仓数据库 SQL 防火墙实战解析

欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 从「亡羊补牢」到「规则先行」:金仓数据库 SQL 防火墙实战解析 * 一、SQL 注入原理 * 典型攻击示例 * 传统防御的局限 * 二、SQL 防火墙原理概述 * 三、核心优势 * 1. 99.99% 准确率 * 2. 性能稳定,损耗极低 * 3. 两步完成配置,自动建立白名单 * 四、配置操作演示 * 第一步:启用插件 * 第二步:进入学习模式,采集白名单 * 第三步:切换警告模式,验证白名单 * 第四步:切换报错模式,正式防护 * 五、总结 SQL 注入是数据库安全最顽固的威胁之一。

By Ne0inhk
【MySQL】第六节—一文详解 | 表的约束(下)

【MySQL】第六节—一文详解 | 表的约束(下)

Hello,2026 我们见面啦!我是云边有个稻草人,新年第一篇U·ェ·U,ACTION! 《MySQL》本篇文章所属专栏—持续更新中—欢迎订阅! 目录 6、自增长 auto_increment  7、唯一键 unique  8、外键 foreign key  9、综合案例 - 阅读  【MySQL】第五节—一文详解 | 表的约束(上)-ZEEKLOG博客 正文开始—— 6、自增长 auto_increment  auto_increment:当对应的字段,不给值,会自动的被系统触发,系统会从当前字段中已经有的最大值 +1操作,得到一个新的不同的值。通常和主键搭配使用(被设置为主键),作为逻辑主键。

By Ne0inhk
HarmonyOS6半年磨一剑 - RcImage组件核心架构与状态管理机制

HarmonyOS6半年磨一剑 - RcImage组件核心架构与状态管理机制

文章目录 * 前言 * 项目简介 * 核心特性 * 开源计划 * rchoui官网 * 第一章: 组件架构设计 * 1.1 ComponentV2 装饰器体系 * 1.2 参数系统分层设计 * 1.3 类型系统设计 * 第二章: 状态管理机制 * 2.1 加载状态机设计 * 2.2 状态转换逻辑实现 * 2.3 预览状态管理 * 第三章: 生命周期管理 * 3.1 组件生命周期钩子 * 3.2 状态更新触发机制 * 第四章: 事件系统设计 * 4.1 事件分类与职责 * 4.2 事件触发时机与顺序 * 4.3 事件参数设计 * 第五章: 渲染优化策略

By Ne0inhk