码道:# 手把手教你用 FastAPI 十分钟搞定一个学生信息管理系统:从零到 Swagger 文档 > 全文约 3200 字,阅读约需 8 分钟。读完你将获得一个完整可运行的「学生信息增删改查」后
手把手教你用 FastAPI 十分钟搞定一个学生信息管理系统:从零到 Swagger 文档
全文约 3200 字,阅读约需 8 分钟。读完你将获得一个完整可运行的「学生信息增删改查」后端项目,并理解 FastAPI 的核心用法。
一、为什么选择 FastAPI
在日常开发中,「增删改查」(CRUD)是绝大多数业务系统的基础能力。无论是学生管理系统、会议管理系统还是电商后台,本质上都是对数据的增删改查。过去我们习惯用 Django、Flask 等框架来实现,但从 2018 年 FastAPI 发布以来,它以惊人的迭代速度成为 Python Web 生态中备受青睐的框架。
FastAPI 的优势非常突出。第一,它基于 Python 的类型注解(Type Hint)进行数据校验和序列化,写一份模型就能同时得到请求参数校验、数据转换和接口文档,等于一份代码三份收益。第二,它原生支持异步(async/await)处理高并发请求,性能表现直逼 Go 和 Node.js。第三,它自动生成 OpenAPI 规范的接口文档,访问 /docs 就能看到交互式的 Swagger UI 页面,前端同事可以直接在页面上测试接口,几乎为零沟通成本。
本篇文章,我们就用 FastAPI 从零搭建一个学生信息管理系统,数据直接用内存列表存储,不依赖任何数据库。麻雀虽小,五脏俱全,通过这个项目你可以完整地理解一个现代 Python Web 项目的工程结构。
二、项目设计:先想清楚再动手
动手写代码之前,先对需求进行拆解。我们要实现的核心功能有五个:查询学生列表、查询单个学生、新增学生、更新学生信息、删除学生。这是最标准的 RESTful CRUD 接口。
在数据结构方面,一个学生记录需要包含这些字段:唯一 ID(自增)、姓名、年龄、性别、邮箱、班级,以及一个可选的绩点(GPA)。其中 ID 由系统生成,其余字段由调用方传入。
存储方案上,用户明确要求使用内存列表存储,因此我们使用 Python 内置的 list 作为数据载体。为了让数据在并发访问时不出现错乱,我们引入 threading.Lock 给读写操作加上线程锁。虽然加锁会带来一些性能开销,但对于一个演示项目来说,正确性远比极致性能重要。
接口设计遵循 RESTful 风格:GET /api/students 查询列表,GET /api/students/{id} 查询详情,POST /api/students 新增,PUT /api/students/{id} 更新,DELETE /api/students/{id} 删除。查询列表接口还支持分页、按姓名关键字模糊搜索、按性别和班级过滤,这些都是真实业务中最常见的能力。
项目目录结构采用「分层」思路:models.py 负责数据模型定义,storage.py 负责数据存取,routers/students.py 负责接口路由,main.py 负责应用装配。这样的分层可以让每个文件职责单一,后续扩展功能(比如接入 MySQL)时只需要替换 storage 层即可。
三、代码详解:三层架构各司其职
3.1 模型层:用 Pydantic 定义数据结构
我们使用 Pydantic v2 的 BaseModel 来定义数据模型。先定义一个 StudentBase 作为公共基类,包含姓名、年龄、性别、邮箱、班级、绩点这些字段,并为每个字段加上校验规则:姓名最短 1 个字符最长 50 个字符,年龄必须在 1 到 150 之间,绩点在 0 到 5 之间且允许为空。
接着定义三种具体模型:StudentCreate(新增请求体)、StudentUpdate(更新请求体,所有字段可选,支持部分更新)、Student(响应模型,包含自增 ID)。除此之外,我们还需要 StudentPage 作为分页查询的响应结构,以及 MessageResponse 作为删除等操作的统一返回。
这样设计的最大好处是:当你往请求接口传一个年龄为 200 岁、或者漏掉姓名的数据时,FastAPI 会在进入业务逻辑之前就拒绝请求并返回 422 状态码和明确的错误信息,我们完全不需要手写任何一行校验代码。
3.2 存储层:内存列表加锁保证安全
存储层是项目的核心逻辑所在。全局变量 _students 是一个列表,_next_id 记录下一个可用的 ID 编号,_lock 是一把线程锁。每次新增学生时,先通过 _gen_id() 拿到自增 ID,然后构造 Student 对象追加到列表尾部。
查询列表时支持三个过滤条件:关键字(对姓名做不区分大小写的子串匹配)、性别(精确匹配)、班级(精确匹配),然后做分页切片返回。更新学生时采用「部分更新」策略:遍历列表找到目标对象后,依次把请求体里显式传了且不为空的字段更新进去。删除操作则直接 pop 掉对应位置。
所有读写操作都包在 with _lock: 中,这意味着任意时刻只有一个线程能改动数据,从根本上避免了「两个请求同时修改同一条数据」的竞态问题。虽然内存存储的代码很简单,但它体现了分层设计的思想:上层路由只需要调用 storage.create_student() 这类方法,完全不关心数据是放在内存里还是数据库里。
3.3 路由层:五个接口一目了然
路由层使用 FastAPI 的 APIRouter 来组织,统一挂在 /api/students 前缀下。每个路由函数都通过装饰器标注 HTTP 方法和路径,并通过参数定义查询参数和请求体。
在查询列表接口中,keyword、gender、class_name、page、page_size 都是查询参数,其中 page_size 被限制在 1 到 100 之间。新增接口返回 status_code=201,符合 REST 语义。当目标学生不存在时,路由直接抛出 HTTPException(status_code=404),FastAPI 会自动把它转成带 detail 信息的 JSON 错误响应。
每个路由函数都配置了 summary 和 description,这些描述会原样呈现在 Swagger 文档里,相当于让接口文档「长在代码上」,永远与代码保持同步。
3.4 应用入口:一行代码装配出文档
main.py 中创建一个 FastAPI 实例,配置好标题、版本号和描述,然后调用 app.include_router(students.router) 把路由挂载进来,整个服务就完成了。访问 /docs 会自动呈现 Swagger UI,所有接口的参数说明、请求示例、返回结构一目了然,还支持在线试调用。
四、跑起来看看效果
项目依赖只需要三个包:FastAPI、Uvicorn(ASGI 服务器)、Pydantic。执行 pip install -r requirements.txt 安装依赖,然后运行 uvicorn app.main:app --reload 启动服务,浏览器打开 http://127.0.0.1:8000/docs 就能看到接口文档页面。
在 Swagger 页面上,我们可以直接点击 Post 接口,填入一条学生数据点击执行,状态码 201,返回体里带着自动生成的 ID。用同样的方式依次测试查询、更新、删除,全部流程一气呵成。如果我们故意把年龄写成 200,服务会返回 422 和「Input should be less than or equal to 150」的错误提示,这正是 Pydantic 校验在起作用。
也可以用 curl 在命令行调用。比如新增学生:
curl -X POST http://127.0.0.1:8000/api/students \
-H "Content-Type: application/json" \
-d '{"name":"张三","age":18,"gender":"男","email":"zhangsan@example.com","class_name":"高一(1)班","gpa":3.8}'
查询列表、按关键字搜索、删除学生等操作也都是一行 curl 的事。这种「无数据库、零配置」的项目特别适合作为前后端联调的桩服务,或者作为学习 FastAPI 的第一个练手项目。
五、踩坑与思考
在实现过程中有几个值得注意的细节。第一,Pydantic v2 相对 v1 有较大变更,最典型的是 dict() 方法改名为 model_dump(),如果你习惯看 v1 的旧教程,很容易踩坑。第二,StudentUpdate 使用 exclude_unset=True 来区分「没传」和「传了 null」,这是实现部分更新的关键技巧。第三,内存存储的多进程问题:如果使用 Gunicorn 多 worker 部署,每个进程各自持有一份内存数据,请求打到不同 worker 上看到的不是同一份数据,所以在生产环境必须换成数据库。
关于项目后续的演进方向,可以这样规划:第一优先级是把存储层替换为 SQLite,storage.py 中的方法签名保持不变,路由代码一行都不用改,这正好检验了分层设计的价值。第二优先级是接入 MySQL/PostgreSQL,并增加 ORM 映射。第三优先级是补充单元测试,FastAPI 自带 TestClient,可以对每个接口做断言测试。再往后还可以加登录鉴权、上传头像、导出 Excel 等业务能力。
六、结语
从需求拆解、模型定义、存储实现到路由装配,不到两百行 Python 代码,我们就完成了一个带 Swagger 文档、带参数校验、带并发保护的学生信息管理系统。这个项目的意义不在于功能本身多强大,而在于演示了 FastAPI 的核心用法和一个清晰的分层工程结构。
FastAPI 用「类型即文档」的理念,大幅降低了接口开发的重复劳动。如果你正在入门 Python Web 开发,或者需要一个快速原型来验证想法,强烈建议动手实践一遍这个项目。你也完全可以把这个骨架复制出去,把「学生」换成「订单」「文章」「任务」,半小时就能搭起下一个业务系统的雏形。
技术就是这样,重要的永远不是记住某个 API,而是理解它背后的设计哲学,然后在自己的项目里举一反三。
项目地址: https://atomgit.com/sy5875668/sy
快速体验: 克隆仓库后执行 pip install -r requirements.txt && uvicorn app.main:app --reload,然后用浏览器打开 http://127.0.0.1:8000/docs 即可在线调试全部接口。
更多推荐


所有评论(0)