FastAPI 实战:构建待办事项 Web API 的增删改查全流程

一、FastAPI 简介与项目初始化

FastAPI 是一个基于 Python 的现代 Web 框架,用于快速构建 API。它利用 Python 类型注解实现自动文档生成(Swagger UI 和 ReDoc),并支持异步请求处理,性能接近 Node.js 和 Go。相比 Flask 和 Django,FastAPI 更轻量且适合 API 开发。

1.1 环境准备

首先,确保已安装 Python 3.7+ 和 pip。创建虚拟环境并安装 FastAPI 和 Uvicorn(ASGI 服务器):

  1. python -m venv venv
  2. source venv/bin/activate # Linux/macOS
  3. venv\Scripts\activate # Windows
  4. pip install fastapi uvicorn

1.2 项目结构

推荐结构如下:

  1. todo_api/
  2. ├── main.py # 入口文件
  3. ├── models.py # 数据模型
  4. ├── schemas.py # 请求/响应模型(Pydantic)
  5. ├── crud.py # 数据库操作
  6. └── requirements.txt # 依赖文件

二、定义数据模型与 Pydantic 模式

2.1 数据模型(models.py)

使用 SQLModel(结合 SQLAlchemy 和 Pydantic)定义待办事项模型:

  1. from sqlmodel import SQLModel, Field
  2. from typing import Optional
  3. class Todo(SQLModel, table=True):
  4. id: Optional[int] = Field(default=None, primary_key=True)
  5. title: str = Field(max_length=100)
  6. description: Optional[str] = Field(default=None)
  7. completed: bool = Field(default=False)

2.2 请求/响应模式(schemas.py)

使用 Pydantic 定义数据验证模式:

  1. from pydantic import BaseModel
  2. from typing import Optional
  3. class TodoBase(BaseModel):
  4. title: str
  5. description: Optional[str] = None
  6. completed: bool = False
  7. class TodoCreate(TodoBase):
  8. pass
  9. class TodoUpdate(TodoBase):
  10. pass
  11. class Todo(TodoBase):
  12. id: int
  13. class Config:
  14. orm_mode = True # 支持 SQLModel 对象转换

三、实现 CRUD 操作(crud.py)

3.1 数据库连接与初始化

使用 sqlmodel.Session 管理数据库会话:

  1. from sqlmodel import SQLModel, create_engine, Session
  2. from typing import Optional
  3. from .models import Todo
  4. # SQLite 内存数据库(生产环境替换为 PostgreSQL/MySQL)
  5. engine = create_engine("sqlite:///todos.db")
  6. def init_db():
  7. SQLModel.metadata.create_all(engine)

3.2 核心 CRUD 函数

  1. def get_todos(session: Session):
  2. return session.query(Todo).all()
  3. def get_todo(session: Session, todo_id: int):
  4. return session.query(Todo).filter(Todo.id == todo_id).first()
  5. def create_todo(session: Session, todo: TodoCreate):
  6. db_todo = Todo.from_orm(todo)
  7. session.add(db_todo)
  8. session.commit()
  9. session.refresh(db_todo)
  10. return db_todo
  11. def update_todo(session: Session, todo_id: int, todo: TodoUpdate):
  12. db_todo = session.query(Todo).filter(Todo.id == todo_id).first()
  13. if db_todo:
  14. todo_data = todo.dict(exclude_unset=True)
  15. for key, value in todo_data.items():
  16. setattr(db_todo, key, value)
  17. session.commit()
  18. return db_todo
  19. def delete_todo(session: Session, todo_id: int):
  20. db_todo = session.query(Todo).filter(Todo.id == todo_id).first()
  21. if db_todo:
  22. session.delete(db_todo)
  23. session.commit()
  24. return db_todo is not None

四、构建 FastAPI 路由

4.1 初始化 FastAPI 应用

main.py 中:

  1. from fastapi import FastAPI, Depends, HTTPException
  2. from sqlmodel import Session
  3. from .crud import init_db, get_todos, get_todo, create_todo, update_todo, delete_todo
  4. from .models import Todo
  5. from .schemas import TodoCreate, TodoUpdate
  6. from .database import SessionLocal # 需在 database.py 中定义
  7. app = FastAPI()
  8. # 依赖项:获取数据库会话
  9. def get_db():
  10. with SessionLocal() as session:
  11. yield session
  12. @app.on_event("startup")
  13. async def startup():
  14. init_db()

4.2 实现增删改查路由

  1. # 创建待办事项
  2. @app.post("/todos/", response_model=Todo)
  3. def create_todo_route(todo: TodoCreate, db: Session = Depends(get_db)):
  4. return create_todo(db, todo)
  5. # 获取所有待办事项
  6. @app.get("/todos/", response_model=list[Todo])
  7. def read_todos(db: Session = Depends(get_db)):
  8. return get_todos(db)
  9. # 获取单个待办事项
  10. @app.get("/todos/{todo_id}", response_model=Todo)
  11. def read_todo(todo_id: int, db: Session = Depends(get_db)):
  12. db_todo = get_todo(db, todo_id)
  13. if db_todo is None:
  14. raise HTTPException(status_code=404, detail="Todo not found")
  15. return db_todo
  16. # 更新待办事项
  17. @app.put("/todos/{todo_id}", response_model=Todo)
  18. def update_todo_route(todo_id: int, todo: TodoUpdate, db: Session = Depends(get_db)):
  19. db_todo = update_todo(db, todo_id, todo)
  20. if db_todo is None:
  21. raise HTTPException(status_code=404, detail="Todo not found")
  22. return db_todo
  23. # 删除待办事项
  24. @app.delete("/todos/{todo_id}")
  25. def delete_todo_route(todo_id: int, db: Session = Depends(get_db)):
  26. success = delete_todo(db, todo_id)
  27. if not success:
  28. raise HTTPException(status_code=404, detail="Todo not found")
  29. return {"message": "Todo deleted successfully"}

五、运行与测试 API

5.1 启动服务

  1. uvicorn main:app --reload

服务默认运行在 http://127.0.0.1:8000

5.2 测试 API

使用 curlHTTPie 测试:

  • 创建待办事项

    1. curl -X POST "http://127.0.0.1:8000/todos/" -H "Content-Type: application/json" -d '{"title": "Learn FastAPI", "description": "Build a TODO API"}'
  • 获取所有待办事项

    1. curl "http://127.0.0.1:8000/todos/"
  • 更新待办事项

    1. curl -X PUT "http://127.0.0.1:8000/todos/1" -H "Content-Type: application/json" -d '{"title": "Learn FastAPI", "completed": true}'
  • 删除待办事项

    1. curl -X DELETE "http://127.0.0.1:8000/todos/1"

5.3 自动生成的文档

访问 http://127.0.0.1:8000/docs(Swagger UI)或 http://127.0.0.1:8000/redoc(ReDoc)查看交互式文档。

六、进阶优化建议

  1. 数据库持久化:替换 SQLite 为 PostgreSQL/MySQL,并配置连接池。
  2. 异步支持:使用 SQLModel 的异步版本(需 asyncpg)。
  3. 认证与授权:集成 JWT 或 OAuth2。
  4. 分页与过滤:在 get_todos 中添加分页参数(如 skiplimit)。
  5. 单元测试:使用 pytest 编写测试用例。

七、总结

通过本文,您已掌握如何使用 FastAPI 快速开发一个完整的待办事项 Web API,包括:

  • 项目初始化与环境配置。
  • 数据模型与 Pydantic 模式定义。
  • 核心 CRUD 操作实现。
  • 路由设计与依赖注入。
  • 服务运行与 API 测试。

FastAPI 的高性能和自动文档特性使其成为构建现代 Web API 的理想选择。