logo

FastAPI 待办事项API实战:从零构建CRUD路由

作者:JC2025.09.23 11:56浏览量:1

简介:本文通过实战案例,详细讲解如何使用FastAPI框架快速开发一个支持增删改查(CRUD)的待办事项Web API项目,涵盖路由设计、数据模型、依赖注入及测试全流程。

FastAPI 待办事项API实战:从零构建CRUD路由

一、FastAPI框架优势与待办事项API场景

FastAPI作为基于Python的现代Web框架,凭借其自动生成OpenAPI文档、类型注解支持、异步请求处理等特性,成为开发高性能API的首选。在待办事项管理场景中,用户需要通过API实现任务创建、读取、更新和删除等操作,这对路由设计的清晰性和数据验证的严谨性提出了高要求。

以一个典型待办事项应用为例,用户可能通过移动端或Web前端提交任务数据,后端API需确保数据完整性(如必填字段、日期格式)并返回标准化响应。FastAPI的Body验证和Path参数解析功能可高效处理这类需求,同时其内置的ASGI服务器支持高并发请求。

二、项目初始化与依赖配置

1. 环境搭建

使用Python 3.8+环境,通过pip install fastapi uvicorn安装核心依赖。推荐创建虚拟环境隔离项目依赖:

  1. python -m venv venv
  2. source venv/bin/activate # Linux/Mac
  3. venv\Scripts\activate # Windows

2. 项目结构

采用分层架构设计:

  1. todo_api/
  2. ├── main.py # 入口文件
  3. ├── models.py # 数据模型
  4. ├── schemas.py # 请求/响应模型
  5. ├── crud.py # 数据操作逻辑
  6. └── tests/ # 测试用例

3. 基础路由设置

main.py中初始化FastAPI应用,并添加根路由测试接口:

  1. from fastapi import FastAPI
  2. app = FastAPI()
  3. @app.get("/")
  4. async def read_root():
  5. return {"message": "待办事项API服务已启动"}

三、数据模型与请求验证

1. Pydantic模型定义

schemas.py中定义任务数据的请求/响应模型,利用Pydantic的验证机制确保数据合法性:

  1. from pydantic import BaseModel, Field
  2. from datetime import date
  3. class TodoCreate(BaseModel):
  4. title: str = Field(..., min_length=3, max_length=50)
  5. description: str | None = Field(None, max_length=200)
  6. due_date: date | None = None
  7. priority: int = Field(1, ge=1, le=5) # 1-5级优先级
  8. class TodoUpdate(BaseModel):
  9. title: str | None = None
  10. description: str | None = None
  11. due_date: date | None = None
  12. priority: int | None = None
  13. is_completed: bool | None = None
  14. class TodoResponse(TodoCreate):
  15. id: int
  16. is_completed: bool = False

2. 内存数据存储

为简化演示,使用字典模拟数据库存储(实际项目可替换为SQLAlchemy或Tortoise-ORM):

  1. # crud.py
  2. from typing import Dict, List
  3. from schemas import TodoCreate, TodoUpdate, TodoResponse
  4. db: Dict[int, TodoResponse] = {}
  5. next_id = 1
  6. def get_todos() -> List[TodoResponse]:
  7. return list(db.values())
  8. def create_todo(todo: TodoCreate) -> TodoResponse:
  9. global next_id
  10. new_todo = TodoResponse(id=next_id, **todo.dict())
  11. db[next_id] = new_todo
  12. next_id += 1
  13. return new_todo
  14. # 其他CRUD函数...

四、CRUD路由实现详解

1. 创建任务(POST /todos/)

  1. from fastapi import APIRouter, HTTPException
  2. from schemas import TodoCreate, TodoResponse
  3. import crud
  4. router = APIRouter()
  5. @router.post("/", response_model=TodoResponse)
  6. async def create_todo(todo: TodoCreate):
  7. try:
  8. return crud.create_todo(todo)
  9. except Exception as e:
  10. raise HTTPException(status_code=400, detail=str(e))

关键点

  • 使用response_model自动序列化响应
  • 通过HTTPException处理业务异常
  • 请求体自动由Pydantic模型验证

2. 查询任务(GET /todos/ 与 GET /todos/{id})

  1. @router.get("/")
  2. async def read_todos():
  3. return {"todos": crud.get_todos()}
  4. @router.get("/{todo_id}", response_model=TodoResponse)
  5. async def read_todo(todo_id: int):
  6. if todo_id not in crud.db:
  7. raise HTTPException(status_code=404, detail="任务未找到")
  8. return crud.db[todo_id]

优化实践

  • 添加分页参数:limit: int = 10, offset: int = 0
  • 支持按状态过滤:completed: bool | None = None

3. 更新任务(PUT /todos/{id})

  1. @router.put("/{todo_id}", response_model=TodoResponse)
  2. async def update_todo(todo_id: int, todo_update: TodoUpdate):
  3. if todo_id not in crud.db:
  4. raise HTTPException(404)
  5. todo = crud.db[todo_id]
  6. update_data = todo_update.dict(exclude_unset=True)
  7. updated_todo = todo.copy(update=update_data)
  8. crud.db[todo_id] = updated_todo
  9. return updated_todo

技术要点

  • exclude_unset=True避免覆盖未修改字段
  • 使用字典的copy(update=)方法实现部分更新

4. 删除任务(DELETE /todos/{id})

  1. @router.delete("/{todo_id}")
  2. async def delete_todo(todo_id: int):
  3. if todo_id not in crud.db:
  4. raise HTTPException(404)
  5. del crud.db[todo_id]
  6. return {"message": "任务删除成功"}

安全建议

  • 添加权限验证中间件
  • 软删除替代物理删除(标记is_deleted字段)

五、路由整合与启动服务

main.py中整合路由并启动服务:

  1. from fastapi import FastAPI
  2. from todo_router import router as todo_router
  3. app = FastAPI()
  4. app.include_router(todo_router, prefix="/todos", tags=["待办事项"])
  5. if __name__ == "__main__":
  6. import uvicorn
  7. uvicorn.run(app, host="0.0.0.0", port=8000)

启动参数说明

  • --reload:开发模式自动重载
  • --workers 4:生产环境多进程配置

六、API测试与文档验证

1. 自动生成OpenAPI文档

访问http://localhost:8000/docs,Swagger UI提供交互式测试界面:
Swagger UI示例

2. 使用HTTPie测试

  1. # 创建任务
  2. http POST :8000/todos/ title="学习FastAPI" priority=3
  3. # 查询所有任务
  4. http GET :8000/todos/
  5. # 更新任务
  6. http PUT :8000/todos/1 is_completed=true

3. 单元测试示例

tests/test_todo.py中编写pytest用例:

  1. from fastapi.testclient import TestClient
  2. from main import app
  3. client = TestClient(app)
  4. def test_create_todo():
  5. response = client.post("/todos/", json={
  6. "title": "测试任务",
  7. "priority": 2
  8. })
  9. assert response.status_code == 200
  10. assert "id" in response.json()

七、进阶优化方向

  1. 持久化存储:集成SQLite或PostgreSQL
  2. 认证授权:添加JWT或OAuth2.0支持
  3. 异步处理:使用async/await优化IO操作
  4. 性能监控:集成Prometheus指标收集
  5. API版本控制:通过路由前缀实现/v1/todos/

八、完整代码示例

  1. # main.py 完整示例
  2. from fastapi import FastAPI, HTTPException
  3. from pydantic import BaseModel
  4. from typing import Dict, Optional
  5. from datetime import date
  6. app = FastAPI()
  7. class Todo(BaseModel):
  8. title: str
  9. description: Optional[str] = None
  10. due_date: Optional[date] = None
  11. priority: int = 1
  12. is_completed: bool = False
  13. db: Dict[int, Todo] = {}
  14. next_id = 1
  15. @app.post("/todos/")
  16. async def create_todo(todo: Todo):
  17. global next_id
  18. todo_dict = todo.dict()
  19. todo_dict["id"] = next_id
  20. db[next_id] = Todo(**todo_dict)
  21. next_id += 1
  22. return todo_dict
  23. @app.get("/todos/{todo_id}")
  24. async def get_todo(todo_id: int):
  25. if todo_id not in db:
  26. raise HTTPException(404, "任务不存在")
  27. return db[todo_id]
  28. # 其他路由实现...

通过以上步骤,开发者可快速构建一个功能完整的待办事项API服务。FastAPI的强类型支持和自动化工具链能显著提升开发效率,建议结合实际业务需求逐步扩展功能模块。

相关文章推荐

发表评论

活动