# todo-fastapi **Repository Path**: wangdong_cmcc/todo-fastapi ## Basic Information - **Project Name**: todo-fastapi - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-21 - **Last Updated**: 2026-05-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: 待办事项-fastapi, fastpi待办事项 ## README # todo-fastapi 设计文档 ## 概述 基于 FastAPI 框架的待办事项(Todo)管理 API 项目,提供完整的 RESTful CRUD 操作和浏览器端管理界面。 - **框架**: FastAPI 0.136 + Pydantic 2.13 - **Python**: 3.13+ - **数据库**: MariaDB (MySQL) + SQLAlchemy 2.0 + PyMySQL - **自动文档**: Swagger UI (`/docs`) ## 效果展示 ![Web 管理页面](todo-main.png) ![API 文档页面](todo-doc.png) ## 项目结构 ``` todo-fastapi/ ├── main.py # FastAPI 应用入口 ├── models.py # Pydantic 模型 ├── database.py # SQLAlchemy 引擎、ORM 模型、get_db 依赖 ├── settings.py # 配置管理 ├── clean.sh # 提交前清理脚本 ├── routers/ │ └── todos.py # CRUD 端点 ├── templates/ │ └── index.html # 浏览器端管理页面 ├── static/todos/ │ ├── css/style.css # 样式文件 │ └── js/ │ ├── api.js # API 客户端 │ └── app.js # UI 逻辑 ├── todo-main.png ├── todo-doc.png ├── docs/ │ ├── framework_overview.md # 框架与组件总览(含 Uvicorn / Starlette / FastAPI / Pydantic / │ │ # pydantic-settings / main.py 结构说明) │ ├── reading_guide.md # 代码阅读指南 │ ├── troubleshooting.md # 常见问题排查 │ ├── environment.md # 环境切换说明(开发/生产) │ ├── RESTful-API-Python-Guide.md │ └── prompt-engineering-fastapi.md ├── tests/ │ └── test_api.py # pytest 测试(14 个用例) └── requirements.txt ``` ## 架构设计 ``` 浏览器 ──GET /──→ FastAPI ──→ index.html (Jinja2) 浏览器 ──fetch──→ /api/todos ──→ Router ──→ MariaDB (SQLAlchemy ORM) ``` ### 分层职责 | 层 | 文件 | 职责 | |----|------|------| | 入口 | `main.py` | 创建 FastAPI 实例,注册路由,挂载模板/静态文件,启动时建表 | | 路由 | `routers/todos.py` | HTTP 端点定义,请求分发,状态码控制,依赖注入 | | 模型 | `models.py` | Pydantic Schema:请求验证、响应序列化 | | 存储 | `database.py` | SQLAlchemy 引擎配置、ORM 模型定义、会话工厂 | | 视图 | `templates/index.html` | 纯前端 SPA,通过 fetch() 调用 API | | 前端模块 | `static/todos/js/{api,app}.js` | API 客户端 + UI 逻辑 | | 样式 | `static/todos/css/style.css` | 独立样式文件 | ### URL 设计 | 路径 | 方法 | 说明 | |------|------|------| | `/` | GET | Web 管理页面 | | `/api` | GET | API 健康检查 | | `/docs` | GET | Swagger 自动文档 | | `/api/todos/` | GET | 获取列表 | | `/api/todos/` | POST | 创建事项 | | `/api/todos/{id}` | GET | 获取单个 | | `/api/todos/{id}` | PUT | 更新事项 | | `/api/todos/{id}` | DELETE | 删除事项 | ## 关键设计决策 ### 1. 独立的请求/响应模型 三种 Pydantic 模型各司其职: ```python TodoCreate # 创建请求:title 必填,description/completed 可选 TodoUpdate # 更新请求:所有字段可选(Partial Update) Todo # 响应模型:包含 id、created_at、updated_at TodoList # 列表响应:items + total 元数据 ``` 优势:创建时要求 title 必填,更新时所有字段可选,响应中包含服务端生成的字段。 ### 2. MariaDB + SQLAlchemy 存储 `database.py` 中配置 MariaDB 引擎和 ORM 模型: - 连接本地 `todo_fastapi` 数据库,数据持久化 - `get_db()` 依赖注入函数提供会话,请求结束后自动关闭 - `Todo` 响应模型启用 `from_attributes=True`,支持从 ORM 实例直接序列化 ### 3. 部分更新实现 PUT 方法使用 `model_dump(exclude_unset=True)` 提取客户端显式提供的字段,遍历后 `setattr` 到 ORM 对象,其余字段保持不变: ```python update_data = payload.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(todo, field, value) ``` `updated_at` 通过 SQLAlchemy `onupdate` 自动更新。 ### 4. 分离 API 与前端 - API 端点统一以 `/api/` 前缀隔离 - 浏览器访问 `/` 返回单页 HTML,通过 JavaScript `fetch()` 调用 API - 前端和后端通过 JSON 格式交换数据 ### 5. 同步架构 所有端点使用同步 `def`,不引入 async 复杂度。通过 PyMySQL 驱动连接 MariaDB。 ## 为什么需要后端? 对于 Todo 这样的简单业务,纯前端(localStorage / IndexedDB)也能实现功能,但引入 Python 后端服务于以下目的: ### 1. 真正的数据持久化 纯前端存储的数据绑定在单个浏览器中,换设备、清缓存或重装后数据即丢失。后端数据库提供独立于客户端的持久化存储,数据不依赖浏览器环境。 ### 2. API 作为契约边界 后端明确定义了请求/响应格式(Pydantic 模型)、状态码、校验规则。这意味着: - 前端可以换成任何客户端:CLI 工具、移动 App、第三方集成 - 多个前端可以共享同一套数据 - API 文档(Swagger UI)自动生成,便于调试和对接 ### 3. 服务端控制 集中管理权限、频率限制、数据校验、审计日志等安全策略,前端只负责展示和交互。 ### 4. 技术栈演示 作为教学项目,核心价值是展示 **FastAPI + SQLAlchemy + MariaDB 这套技术栈如何组合**,理解前后端分离架构中每一层的职责,为构建真实项目打好基础。 > 一句话:Todo 只是载体,分层架构才是内容。 ## 安装与运行 ### 环境要求 - Python 3.13+ - MariaDB (MySQL) 服务运行中 - pip(或 uv 等包管理器) ### 数据库安装与配置 #### 安装 MariaDB ##### macOS(Homebrew) ```bash # 安装 MariaDB brew install mariadb # 启动服务 brew services start mariadb # 验证服务状态 mysqladmin ping ``` ##### Ubuntu / Debian ```bash sudo apt update sudo apt install mariadb-server sudo systemctl start mariadb ``` ##### Windows 从 [mariadb.org](https://mariadb.org/download/) 下载安装包,安装后启动 `mysqld` 服务。 ### 创建虚拟环境并安装依赖 推荐使用虚拟环境隔离项目依赖: ```bash # 创建虚拟环境 python3 -m venv .venv # 激活虚拟环境 source .venv/bin/activate # macOS / Linux # .venv\Scripts\activate # Windows # 安装依赖 pip install -r requirements.txt ``` ### 依赖说明 | 包 | 作用 | | --- | ------ | | `fastapi[standard]` | Web 框架,提供路由、中间件、参数校验等核心能力;`[standard]` 包含 `fastapi dev` CLI 工具 | | `uvicorn[standard]` | ASGI 服务器,运行 FastAPI 应用;`[standard]` 包含 `--reload` 等开发功能 | | `sqlalchemy` | ORM 框架,定义数据模型、执行数据库查询和会话管理 | | `pymysql` | Python MySQL 驱动,SQLAlchemy 通过它连接 MariaDB | | `jinja2` | 模板引擎,用于渲染 Web 管理页面 `index.html` | | `pydantic-settings` | 配置管理,从环境变量和 `.env` 文件加载配置 | | `pytest` | 测试框架,运行 API 自动化测试 | | `httpx` | HTTP 客户端,`TestClient` 底层用它发送测试请求 | ### 配置数据库连接 项目使用 [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) 管理配置,在 [settings.py](settings.py) 中定义: ```python class Settings(BaseSettings): model_config = {"env_file": ".env", "env_file_encoding": "utf-8"} database_url: str = "mysql+pymysql://todoapp:todoapp123@localhost:3306/todo_fastapi?charset=utf8mb4" ``` 加载优先级(高 → 低): 1. **环境变量** `DATABASE_URL` 2. **`.env` 文件**中的 `DATABASE_URL` 3. **代码中的默认值**(仅本地开发用) **生产环境**必须通过环境变量或 `.env` 文件传入 `DATABASE_URL`,不要依赖默认值。 **设置方式:** ```bash # 方式一:环境变量(推荐生产用) export DATABASE_URL="mysql+pymysql://todoapp:你的密码@localhost:3306/todo_fastapi?charset=utf8mb4" fastapi dev main.py # 方式二:.env 文件(推荐本地开发用) cp .env.example .env # 编辑 .env 修改密码 # 注意:.env 已在 .gitignore 中排除,不会提交到版本控制 ``` > 代码中不包含任何敏感凭据。`.env` 文件包含真实密码,已在 `.gitignore` 中排除。 ### 数据库与表初始化 数据库和表会在应用启动时**自动创建**,无需手动执行 SQL 或脚本。启动日志中会显示: ``` INFO:__main__:正在初始化数据库... INFO:__main__:数据库已就绪 ``` > 首次部署时需要先手动创建数据库用户(已创建过则跳过): > > ```bash > sudo mysql -u root -e " > CREATE USER IF NOT EXISTS 'todoapp'@'localhost' IDENTIFIED BY 'todoapp123'; > GRANT ALL PRIVILEGES ON todo_fastapi.* TO 'todoapp'@'localhost'; > FLUSH PRIVILEGES; > " > ``` ### 启动服务 先确保虚拟环境已激活(`source .venv/bin/activate`),然后: ```bash # 方式一:FastAPI CLI(推荐) fastapi dev main.py # 方式二:Uvicorn uvicorn main:app --reload ``` 服务启动后访问: - Web 管理页面:`http://localhost:8000` - 交互式 API 文档:`http://localhost:8000/docs` ### 提交前清理 ```bash bash clean.sh ``` 清理 `__pycache__`、`*.pyc`、`.pytest_cache`、`*.db` 等编译中间文件。 ### 重置数据 清空数据库表即可重置所有数据: ```bash sudo mysql -u root -e "TRUNCATE TABLE todo_fastapi.todos;" ``` --- ## 生产环境部署 详细的开发/生产环境配置说明及切换方法请参考 [环境配置说明](docs/environment.md)。 快速参考: ```bash # 加载生产配置模板(编辑后使用) source .env.production uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4 ``` ### 部署检查清单 - [ ] `ENVIRONMENT=production` 已设置 - [ ] `DATABASE_URL` 指向正确的生产数据库 - [ ] `CORS_ORIGINS` 配置了前端域名 - [ ] 数据库已创建并可使用 - [ ] 使用 `--workers 4` 或更多 worker 启动 - [ ] 前端反向代理(Nginx/Caddy)配置了 HTTPS 和静态文件缓存 - [ ] 关闭 `/docs`(生产环境可移除 `main.py` 中的 `openapi_url` 参数) ## 测试 使用 `fastapi.testclient.TestClient` + pytest,测试直接连接 MariaDB: ```bash cd todo-fastapi && python -m pytest tests/ -v # 确保虚拟环境已激活 ``` 14 个测试用例覆盖:创建(含验证错误)、列表、获取、更新、删除。