文章目录
- FastCRUD 建立于 FastAPI + SQLAlchemy 异步模型之上,支持 AsyncSession 等异步 API。GitHub 上标注为 “⚡️ Fully Async”。([GitHub][1]) 优势:在高并发 HTTP 请求场景下,更好地利用 I/O 等待时间,不阻塞事件循环。 注意事项:你的数据库驱动、SQLAlchemy 版本、session 配置必须配合异步使用,否则可能出现混用同步/异步问题。
- FastCRUD 要求 SQLAlchemy 版本为 2.0+。([PyPI][3]) 优势:利用最新 SQLAlchemy 的特性(如 2.0 风格的 API、async 支持、改进的 ORM 性能)。 注意事项:如果项目还在用 SQLAlchemy 1.x,升级成本可能不低。
- FastCRUD 在 CRUD 操作方面提供了:create, get, exists, count, get_multi 等通用方法。([PyPI][3]) 此外,它还提供 crud_router,允许你几行代码就生成一个标准的 CRUD 路由器。示例如下:([GitHub][1]) item_router = crud_router( session=get_session, model=Item, create_schema=ItemCreateSchema, update_schema=ItemUpdateSchema, path=”/items”, tags=[“Items”], ) app.include_router(item_router) 优势:极大缩短原型开发时间;适合 CRUD 密集型服务、后台管理系统。 注意事项:自动生成的端点虽然方便,但在复杂业务(权限、校验、复杂逻辑)下可能需要手工调整或替换。
- FastCRUD 支持以下特性: 自动检测 Join 条件 (join 操作) ([GitHub][1]) 排序 (sort_columns, sort_orders) 和分页 (offset/cursor) ([PyPI][3]) Cursor 分页适合“无限滚动”场景。([PyPI][3]) 优势:相比自己手写 select + joins + pagination,这些常见需求已经封装好。 注意事项:虽然支持 join,但并不是万能(例如非常复杂的自定义 SQL、视图、CTE、子查询等可能还是需要手写)。
- FastCRUD 声称自己是 “Modular and Extensible”。([GitHub][1]) 意味着你可以继承、覆盖默认行为(比如你想添加软删除字段、审计字段、特定校验等)。 对于标准化服务非常有用,但一定要看文档/源码以了解扩展方式。
- 假设你已经安装了: pip install fastcrud 并且项目中已有 FastAPI/SQLAlchemy 2 配置。根据 PyPI 信息:FastCRUD 要求 Python 3.9+、SQLAlchemy 2.0.21+、Pydantic 2.4.1+。([PyPI][3])
- models.py: from sqlalchemy import Column, Integer, String from sqlalchemy.orm import DeclarativeBase class Base(DeclarativeBase): pass class Item(Base): __tablename__ = ‘items’ id = Column(Integer, primary_key=True) name = Column(String) description = Column(String) schemas.py: from pydantic import BaseModel class ItemCreateSchema(BaseModel): name: str description: str class ItemUpdateSchema(BaseModel): name: str description: str
- main.py: from fastapi import FastAPI from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker from fastcrud import crud_router from models import Base, Item from schemas import ItemCreateSchema, ItemUpdateSchema DATABASE_URL = “sqlite+aiosqlite:///./test.db” engine = create_async_engine(DATABASE_URL, echo=True) async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) async def get_session() -> AsyncSession: async with async_session() as session: yield session async def lifespan(app: FastAPI): async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield app = FastAPI(lifespan=lifespan) item_router = crud_router( session=get_session, model=Item, create_schema=ItemCreateSchema, update_schema=ItemUpdateSchema, path=”/items”, tags=[“Items”], ) app.include_router(item_router) 启动后,你就会在 /docs 中看到 CRUD 接口(例如 POST /items/, GET /items/{id}, PATCH /items/{id}, DELETE /items/{id},列表接口等)。这个省去了大量重复代码。文章中即有示例。([Medium][2])
- 如果你需要更灵活控制,比如在路径、逻辑、权限等方面,FastCRUD 也支持直接用其 FastCRUD 类。示例:([PyPI][3]) from fastcrud import FastCRUD item_crud = FastCRUD(Item) @app.post(“/custom/items/”) async def create_item(item_data: ItemCreateSchema, db: AsyncSession = Depends(get_session)): return await item_crud.create(db, item_data) @app.get(“/custom/items/{item_id}”) async def read_item(item_id: int, db: AsyncSession = Depends(get_session)): item = await item_crud.get(db, id=item_id) if not item: raise HTTPException(status_code=404, detail=”Item not found”) return item 这样你保留了自定义控制流,同时利用其 CRUD 基础逻辑。
- 根据文档,FastCRUD 提供若干关键方法(摘录自 PyPI): create(db, object: CreateSchemaType) -> ModelType get(db, schema_to_select: Optional[…] = None, **kwargs) exists(db, **kwargs) -> bool count(db, **kwargs) -> int get_multi(db, offset=0, limit=100, schema_to_select=None, sort_columns=None, sort_orders=None, return_as_model=False, **kwargs) -> dict[str, Any] update(db, object: Union[UpdateSchemaType, dict], **kwargs) delete(db, db_row=None, **kwargs)(软删除) db_delete(db, **kwargs)(硬删除) 此外还有更高级如 get_joined、get_multi_joined、get_multi_by_cursor 等用于 join 和 cursor 分页。([PyPI][3])
- crud_router 的实现会内部创建标准的 FastAPI 路由(POST、GET、PATCH、DELETE、列表等),并且使用上面 CRUD 方法作为 handler。它还接受 session factory、model、schema、path、tags 等参数。通过这层抽象,开发者并不需要每次手动写路由定义。
- Offset 分页:通过 offset + limit 参数在 get_multi 方法中支持。 Cursor 分页:通过 get_multi_by_cursor 支持,该方法接受 cursor, limit, sort_column, sort_order 参数。 Sorting:可以传入 sort_columns 和 sort_orders 对应列与方向。 这些都是常见但自己手写较繁琐的逻辑,使用 FastCRUD 可以省掉不少代码。
- get_joined 与 get_multi_joined 方法支持将主模型与其它模型做关联查询。对于 ORM 模型间关系(ForeignKey、relationship)或显式 join_on 条件,FastCRUD 支持自动检测 join 条件。([GitHub][1]) 不过,这里也有“隐藏成本”——如果你的 join 逻辑非常定制(如多级 join、复杂子查询、聚合等),仍可能需要手写 SQL。
- 复杂业务逻辑的灵活性:当业务流程包含大量自定义校验、复杂事务、跨模型操作、子查询/聚合时,自动生成的 CRUD 路径可能不够,需要手写或扩展。 ORM 历史或依赖限制:如果项目仍在用 SQLAlchemy 1.x 或者不同 ORM(如 Tortoise ORM、ORMlite)则不适用。 文档或社区投入:虽然有基本文档,但相比成熟框架/库,可能在边缘场景(例如非常复杂 join、特殊数据库类型)支持较少。Reddit 上就有用户反馈文档在 “why use this” 和 “how exactly generated endpoints look” 方面资料不够详尽。([Reddit][4]) 自动化可能隐藏细节:自动 endpoint 虽然方便,但你可能不清楚默认行为(如软删除、异常处理、返回格式)细节。建议在生产环境使用前明确行为。
- 确保数据模型设计良好(主键、关系、索引、外键等清晰),以便 join 机制能顺利工作。 如果数据库字段类型比较特殊(例如使用 sqlalchemy-utils 的特殊列类型),FastCRUD 文档中提到可能会抛出 NotImplementedError,需要你为该列类型添加 python_type 属性。([GitHub][1]) 在使用 crud_router 生成路由时,默认假设主键字段名为 id(至少在某些版本中如此)——根据 PyPI 描述:“For now, your primary column must be named id or automatic endpoint creation will not work.” ([PyPI][3]) 生产环境中,建议你对生成的端点加入权限验证、访问日志、异常统一处理等中间件,而不仅仅依赖自动路由。 针对分页/排序/过滤的安全考虑(如防止 offset 太大、cursor 被滥用、排序字段注入等)也要做好防护。
目录
- 一、项目背景与定位
- 为什么会有这样一个库?
- 二、核心特性解析
- 2.1 全异步 (Async)
- 2.2 支持 SQLAlchemy 2.0
- 2.3 强大的 CRUD 功能 + 自动生成端点
- 2.4 复杂查询能力:动态排序/分页/联表 (joins)
- 2.5 模块化 & 可扩展设计
- 三、快速上手示例
- 3.1 环境准备
- 3.2 定义模型与 schema
- 3.3 应用配置 & 路由自动生成
- 3.4 在自定义路由中使用
- 四、深入机制剖析
- 4.1 CRUD 类的方法
- 4.2 自动生成 Router 的机制
- 4.3 Pagination & Sorting
- 4.4 Join 支持
- 五、优点 & 使用场景
- 优点
- 使用场景
- 六、局限性 &注意事项
- 局限性
- 注意事项
- 七、实战建议与最佳实践
- 八、总结
FastCRUD 是一个为 FastAPI + SQLAlchemy 场景设计的开源库,由 Benav Labs 维护,旨在简化 CRUD 端点搭建与数据库操作的流程。其 GitHub 仓库描述如下:
“FastCRUD is a Python package for FastAPI, offering robust async CRUD operations and flexible endpoint creation utilities.” ([GitHub][1])
核心特性包括:全异步、支持 SQLAlchemy 2.0、支持 joins、支持动态排序、支持 offset 和 cursor 分页。([GitHub][1])
在使用 FastAPI + SQLAlchemy 时,开发典型的 CRUD 接口(Create/Read/Update/Delete)往往需要重复以下工作:
- 定义 SQLAlchemy 模型(Model)和 Pydantic 模型(Schema)
- 编写增删改查逻辑(Session 管理、commit/refresh、异常处理)
- 在路由里创立对应的 endpoint、设置依赖、处理分页/排序/过滤
- 如果涉及多表关联(join)或复杂查询,则代码量又进一步增加
FastCRUD 正是在这样的场景下诞生:通过抽象通用的 CRUD 操作以及自动生成路由,帮助你用更少的代码快速搭建 API 原型或轻量服务。
例如,在一篇作者介绍文章中提到:“你写了很多重复代码…用 FastCRUD,这些代码可以显著减少”。([Medium][2])
下面逐条解析 FastCRUD 提供的主要特性,并讨论其背后的价值。
FastCRUD 建立于 FastAPI + SQLAlchemy 异步模型之上,支持 AsyncSession 等异步 API。GitHub 上标注为 “⚡️ Fully Async”。([GitHub][1])
- 优势:在高并发 HTTP 请求场景下,更好地利用 I/O 等待时间,不阻塞事件循环。
- 注意事项:你的数据库驱动、SQLAlchemy 版本、session 配置必须配合异步使用,否则可能出现混用同步/异步问题。
FastCRUD 要求 SQLAlchemy 版本为 2.0+。([PyPI][3])
- 优势:利用最新 SQLAlchemy 的特性(如 2.0 风格的 API、async 支持、改进的 ORM 性能)。
- 注意事项:如果项目还在用 SQLAlchemy 1.x,升级成本可能不低。
FastCRUD 在 CRUD 操作方面提供了:create, get, exists, count, get_multi 等通用方法。([PyPI][3]) 此外,它还提供 crud_router,允许你几行代码就生成一个标准的 CRUD 路由器。示例如下:([GitHub][1])
item_router = crud_router(
session=get_session,
model=Item,
create_schema=ItemCreateSchema,
update_schema=ItemUpdateSchema,
path="/items",
tags=["Items"],
)
app.include_router(item_router)
- 优势:极大缩短原型开发时间;适合 CRUD 密集型服务、后台管理系统。
- 注意事项:自动生成的端点虽然方便,但在复杂业务(权限、校验、复杂逻辑)下可能需要手工调整或替换。
FastCRUD 支持以下特性:
- 自动检测 Join 条件 (join 操作) ([GitHub][1])
- 排序 (sort_columns, sort_orders) 和分页 (offset/cursor) ([PyPI][3])
- Cursor 分页适合“无限滚动”场景。([PyPI][3])
- 优势:相比自己手写 select + joins + pagination,这些常见需求已经封装好。
- 注意事项:虽然支持 join,但并不是万能(例如非常复杂的自定义 SQL、视图、CTE、子查询等可能还是需要手写)。
FastCRUD 声称自己是 “Modular and Extensible”。([GitHub][1])
- 意味着你可以继承、覆盖默认行为(比如你想添加软删除字段、审计字段、特定校验等)。
- 对于标准化服务非常有用,但一定要看文档/源码以了解扩展方式。
下面通过一个简单的 “Items” 模型示例演示如何使用 FastCRUD。
假设你已经安装了:
pip install fastcrud
并且项目中已有 FastAPI/SQLAlchemy 2 配置。根据 PyPI 信息:FastCRUD 要求 Python 3.9+、SQLAlchemy 2.0.21+、Pydantic 2.4.1+。([PyPI][3])
models.py:
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String)
description = Column(String)
schemas.py:
from pydantic import BaseModel
class ItemCreateSchema(BaseModel):
name: str
description: str
class ItemUpdateSchema(BaseModel):
name: str
description: str
main.py:
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from fastcrud import crud_router
from models import Base, Item
from schemas import ItemCreateSchema, ItemUpdateSchema
DATABASE_URL = "sqlite+aiosqlite:///./test.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_session() -> AsyncSession:
async with async_session() as session:
yield session
async def lifespan(app: FastAPI):
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
app = FastAPI(lifespan=lifespan)
item_router = crud_router(
session=get_session,
model=Item,
create_schema=ItemCreateSchema,
update_schema=ItemUpdateSchema,
path="/items",
tags=["Items"],
)
app.include_router(item_router)
启动后,你就会在 /docs 中看到 CRUD 接口(例如 POST /items/, GET /items/{id}, PATCH /items/{id}, DELETE /items/{id},列表接口等)。这个省去了大量重复代码。文章中即有示例。([Medium][2])
如果你需要更灵活控制,比如在路径、逻辑、权限等方面,FastCRUD 也支持直接用其 FastCRUD 类。示例:([PyPI][3])
from fastcrud import FastCRUD
item_crud = FastCRUD(Item)
@app.post("/custom/items/")
async def create_item(item_data: ItemCreateSchema, db: AsyncSession = Depends(get_session)):
return await item_crud.create(db, item_data)
@app.get("/custom/items/{item_id}")
async def read_item(item_id: int, db: AsyncSession = Depends(get_session)):
item = await item_crud.get(db, id=item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return item
这样你保留了自定义控制流,同时利用其 CRUD 基础逻辑。
根据文档,FastCRUD 提供若干关键方法(摘录自 PyPI):
create(db, object: CreateSchemaType) -> ModelTypeget(db, schema_to_select: Optional[...] = None, **kwargs)exists(db, **kwargs) -> boolcount(db, **kwargs) -> intget_multi(db, offset=0, limit=100, schema_to_select=None, sort_columns=None, sort_orders=None, return_as_model=False, **kwargs) -> dict[str, Any]update(db, object: Union[UpdateSchemaType, dict], **kwargs)delete(db, db_row=None, **kwargs)(软删除)db_delete(db, **kwargs)(硬删除)
此外还有更高级如 get_joined、get_multi_joined、get_multi_by_cursor 等用于 join 和 cursor 分页。([PyPI][3])
crud_router 的实现会内部创建标准的 FastAPI 路由(POST、GET、PATCH、DELETE、列表等),并且使用上面 CRUD 方法作为 handler。它还接受 session factory、model、schema、path、tags 等参数。通过这层抽象,开发者并不需要每次手动写路由定义。
- Offset 分页:通过
offset + limit 参数在 get_multi 方法中支持。
- Cursor 分页:通过
get_multi_by_cursor 支持,该方法接受 cursor, limit, sort_column, sort_order 参数。
- Sorting:可以传入
sort_columns 和 sort_orders 对应列与方向。
offset + limit 参数在 get_multi 方法中支持。get_multi_by_cursor 支持,该方法接受 cursor, limit, sort_column, sort_order 参数。sort_columns 和 sort_orders 对应列与方向。这些都是常见但自己手写较繁琐的逻辑,使用 FastCRUD 可以省掉不少代码。
get_joined 与 get_multi_joined 方法支持将主模型与其它模型做关联查询。对于 ORM 模型间关系(ForeignKey、relationship)或显式 join_on 条件,FastCRUD 支持自动检测 join 条件。([GitHub][1]) 不过,这里也有“隐藏成本”——如果你的 join 逻辑非常定制(如多级 join、复杂子查询、聚合等),仍可能需要手写 SQL。
- 开发效率高:特别是内部后台服务、CRUD 为主的 API,可以快速上线。
- 代码统一:CRUD 操作集中到类库里,减少重复 Boilerplate。
- 现代技术栈支持:异步、SQLAlchemy 2.0、Pydantic 2.x、FastAPI。
- 可扩展:可以在标准之上加入自定义逻辑。
- 自动路由生成:适合快速原型或内部工具。
- 企业内部后台管理系统(如用户、权限、产品、订单管理)
- 微服务中 CRUD 密集但业务逻辑相对简单的场景
- 快速原型验证,尤其想用 FastAPI 很快搭建接口
- 想统一标准 CRUD 模型、减少重复代码的团队
- 复杂业务逻辑的灵活性:当业务流程包含大量自定义校验、复杂事务、跨模型操作、子查询/聚合时,自动生成的 CRUD 路径可能不够,需要手写或扩展。
- ORM 历史或依赖限制:如果项目仍在用 SQLAlchemy 1.x 或者不同 ORM(如 Tortoise ORM、ORMlite)则不适用。
- 文档或社区投入:虽然有基本文档,但相比成熟框架/库,可能在边缘场景(例如非常复杂 join、特殊数据库类型)支持较少。Reddit 上就有用户反馈文档在 “why use this” 和 “how exactly generated endpoints look” 方面资料不够详尽。([Reddit][4])
- 自动化可能隐藏细节:自动 endpoint 虽然方便,但你可能不清楚默认行为(如软删除、异常处理、返回格式)细节。建议在生产环境使用前明确行为。
- 确保数据模型设计良好(主键、关系、索引、外键等清晰),以便 join 机制能顺利工作。
- 如果数据库字段类型比较特殊(例如使用
sqlalchemy-utils 的特殊列类型),FastCRUD 文档中提到可能会抛出 NotImplementedError,需要你为该列类型添加 python_type 属性。([GitHub][1])
- 在使用
crud_router 生成路由时,默认假设主键字段名为 id(至少在某些版本中如此)——根据 PyPI 描述:“For now, your primary column must be named id or automatic endpoint creation will not work.” ([PyPI][3])
- 生产环境中,建议你对生成的端点加入权限验证、访问日志、异常统一处理等中间件,而不仅仅依赖自动路由。
- 针对分页/排序/过滤的安全考虑(如防止 offset 太大、cursor 被滥用、排序字段注入等)也要做好防护。
sqlalchemy-utils 的特殊列类型),FastCRUD 文档中提到可能会抛出 NotImplementedError,需要你为该列类型添加 python_type 属性。([GitHub][1])crud_router 生成路由时,默认假设主键字段名为 id(至少在某些版本中如此)——根据 PyPI 描述:“For now, your primary column must be named id or automatic endpoint creation will not work.” ([PyPI][3])
- 从原型阶段开始使用自动 router:在项目初期快速搭建 CRUD 路由,验证业务模型、前端交互、数据结构。
- 根据需求分层使用:对于标准 CRUD 模型(如很多后台表格接口),使用
crud_router;对于需要复杂逻辑/权限控制的路由,使用 FastCRUD 类结合自定义逻辑。
- 注重 schema 与模型分离:仍然建议你定义清晰的 Pydantic schema(Create/Update/Read),规范输入输出;避免直接暴露 ORM 模型。
- 做好分页、排序、过滤标准:即便库封装好了,也建议在文档中明确你的分页策略、最大限制、默认排序。
- 审查自动生成的路由:仔细查看自动生成的路径、方法、返回类型、异常处理,确保满足你团队合同/API规范。
- 避免过早升级:虽然库支持 SQLAlchemy 2.0,但如果你的项目还在使用 1.x,最好先评估升级影响。
- 关注社区与维护状态:虽然目前版本可用(截至 2024 年初发布 0.1.4)([PyPI][3]),但生产环境应监控库更新、issue 响应情况、社区反馈。
crud_router;对于需要复杂逻辑/权限控制的路由,使用 FastCRUD 类结合自定义逻辑。
FastCRUD 是一个非常实用的工具,尤其适合你希望用 FastAPI 快速搭建 CRUD 接口、减少重复代码、聚焦核心业务逻辑的场景。它通过全异步支持、SQLAlchemy 2.0、自动路由生成、分页排序 join 支持等特性,实现了 “少写代码、快上线” 的目标。但同时,它并不是万能——对于复杂业务、深度定制、非标准模型或者非 SQLAlchemy ORM 环境,仍需谨慎使用。
在未来,如果你的项目方向是构建一个标准化、可维护、高效的后端服务,FastCRUD 可以作为一个优秀的 “CRUD 基础层”。你可以把它作为 标准 CRUD 模型生成器 + 自定义逻辑插件层,形成 “自动化 + 可扩展” 的架构。
以上就是Python使用FastAPI+FastCRUD自动生成API接口的实现的详细内容,更多关于Python FastAPI+FastCRUD生成API接口的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- Python使用FastAPI+SQLite构建一个短链接生成器服务
- Python使用FastAPI实现文件上传接口的最佳方案
- Python+FastAPI构建一个企业级AI Agent微服务的完整指南
- python基于FastAPI实现一个简易的在线用户统计功能
- Python使用FastAPI实现大文件分片上传与断点续传功能