你是不是也遇到过这样的崩溃时刻?
只想写个简单的 API 接口,却被数据库连接搞得头大 —— 打开了忘关闭,关早了查不到数据;
实现参数验证时,一堆 if-else 绕到头晕;
接口文档还要单独维护,改完代码又得同步更新...;
作为编程新手,只想快速实现「增删改查」全功能 API 接口,怎么这么难吗?”
别急!今天用 FastAPI + SQLAlchemy 手把手教你实现「增删改查」全功能 API 接口。10 分钟搞定数据库连接管理、API 参数验证、自动生成文档需求。
代码直接复制就能跑,新手也能轻松上手~
先明确:API 开发的 3 大痛点,我们要怎么解决?
做接口开发,新手最容易卡壳的 3 个问题:
- 数据库连接混乱:手动管理数据库连接开关易遗漏,导致资源占用;
- 参数验证繁琐:请求体、路径参数要挨个判断合法性,代码冗余;
- 接口文档很麻烦:写完接口还要单独写文档,维护成本很高。
而 FastAPI+SQLAlchemy 的组合拳,能直接命中这些痛点 —— 依赖注入自动管连接、Pydantic 自动做验证、Swagger UI 自动生成文档,让你专注业务逻辑实现,不用再纠结边角料。
实战:5 步搭建全功能 API 接口
00、前置准备
本小节是在上一小节的基础上做的迭代。如需访问上一小节,请点击:跳转
01、依赖注入:解决数据库连接 “自动开关”,再也不用担心漏关了
核心痛点:传统开发中,每次接口请求都要手动创建和关闭数据库会话,繁琐且易错。
解决方案:用 FastAPI 的Depends实现依赖注入,一次定义,所有接口复用。
代码实现(main.py):
from typing import Annotated
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
import models
from database import engine, SessionLocal
app = FastAPI()
# 仅数据库文件不存在时,创建表结构
models.Base.metadata.create_all(bind=engine)
# 定义数据库依赖:自动创建会话,请求结束后自动关闭
def get_db():
db = SessionLocal()
try:
yield db # 先返回会话供接口使用
finally:
db.close() # 无论请求成功与否,都关闭连接
# 封装依赖,后续接口可直接引用
db_dependency = Annotated[Session, Depends(get_db)]
关键亮点:所有接口只需传入db: db_dependency,就能直接操作数据库,不用再写重复的连接 / 关闭代码,彻底解放双手~
02、GET 请求 —— 查全量 / 单条记录,还能做参数校验
查询全量数据记录
代码实现
@app.get("/")
async def read_all(db: db_dependency):
return db.query(models.Todos).all()
直接访问 Swagger UI(FastAPI 自动生成,路径http://127.0.0.1:8000/docs),找到 GET / 点击执行,就能返回数据库中所有记录,无需额外配置!
根据 ID 查询单条记录,避免无效 ID 请求
核心痛点:传入负数 ID、不存在的 ID 时,接口报错很不友好。
解决方案:添加路径参数验证 + 404 错误处理。
代码实现:
from fastapi import Path, HTTPException
from starlette import status
@app.get("/todo/{todo_id}", status_code=status.HTTP_200_OK)
async def read_todo(db: db_dependency, todo_id: int = Path(gt=0)):
# 按ID查询,只取第一条记录
todo_model = db.query(models.Todos).filter(models.Todos.id == todo_id).first()
if todo_model:
return todo_model
# 不存在则返回404
raise HTTPException(status_code=404, detail="Todo not Found")
关键亮点:
Path(gt=0):强制 todo_id 必须大于 0,无效参数直接返回 422 错误,不用手动判断;- 请求成功,明确返回 200 成功状态码,语义更清晰。
03、POST 请求 —— 创建数据记录,请求体自动验证
核心痛点:用户传入的标题太短、优先级超出范围(比如填 10),手动校验很繁琐。
解决方案:用 Pydantic 的BaseModel定义请求体结构,自动做字段校验。
定义请求体模型(自定义校验规则)
from pydantic import BaseModel, Field
class TodoRequest(BaseModel):
title: str = Field(min_length=3) # 标题至少3个字符
description: str = Field(min_length=3, max_length=100) # 描述3-100字符
priority: int = Field(gt=0, lt=6) # 优先级1-5
complete: bool # 是否完成
实现创建接口
@app.post("/todo", status_code=status.HTTP_201_CREATED)
async def create_todo(db: db_dependency, todo_request: TodoRequest):
# 将请求体数据转换为数据库模型
todo_model = models.Todos(**todo_request.dict())
# 新增记录并提交
db.add(todo_model)
db.commit()
打开浏览器的 Swagger UI 页面,刷新页面。打开 POST /todo 接口,在 “Request body” 添加如下内容,并执行它。
{
"title": "Learn FastAPI",
"description": "So I can learn how to create API Endpoint.",
"priority": 5,
"complete": false
}
我们再次执行 GET / 接口请求,就可以查询到这条新创建的记录。
如果优先级填 6,接口会自动返回 422 校验错误。
这里使用 Pydantic 实现请求体验证,不需要写一行 if 判断!
04、PUT 请求 —— 更新记录,避开参数位置的 “坑”
核心需求:根据 ID 更新记录的标题、描述等信息,同时校验 ID 合法性。
第一个坑:参数顺序错误(初始代码如下,会报错)
@app.put("/todo/{todo_id}", status_code=status.HTTP_204_NO_CONTENT)
async def update_todo(db: db_dependency, todo_id: int = Path(gt=0), todo_request: TodoRequest):
# 逻辑代码...
问题:
路径参数(todo_id)和请求体(todo_request)位置颠倒,FastAPI 无法正确解析。
根本原因在于FastAPI依赖函数参数的声明顺序来决定参数的“优先级”和“解析上下文”。
正确代码(调整参数顺序)
@app.put("/todo/{todo_id}", status_code=status.HTTP_204_NO_CONTENT)
async def update_todo(
db: db_dependency,
todo_request: TodoRequest, # 请求体参数放前面
todo_id: int = Path(gt=0) # 路径参数放后面
):
todo_model = db.query(models.Todos).filter(models.Todos.id == todo_id).first()
if not todo_model:
raise HTTPException(status_code=404, detail="Todo not found.")
# 更新字段
todo_model.title = todo_request.title
todo_model.description = todo_request.description
todo_model.priority = todo_request.priority
todo_model.complete = todo_request.complete
db.add(todo_model)
db.commit()
打开浏览器的 Swagger UI 页面,刷新页面。打开 PUT /todo/{todo_id} 接口,传入 todo_id=3,并在 “Request body” 添加如下内容,并执行它。得到响应码 204,表示执行成功。
{
"priority": 1,
"title": "Feed the dog",
"complete": true,
"description": "He is getting hungry"
}
回到 GET / 接口,查看 todo_id=3 的这条记录,内容已经更改成功
# 更新后
{
"description": "He is getting hungry",
"id": 3,
"complete": true,
"title": "Feed the dog",
"priority": 1
}
# 更新前
{
"description": "He is getting hungry",
"id": 3,
"complete": false,
"title": "Feed the dog",
"priority": 3
}
05、DELETE 请求 —— 删除记录
代码实现:
@app.delete("/todo/{todo_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_todo(db: db_dependency, todo_id: int = Path(gt=0)):
todo_model = db.query(models.Todos).filter(models.Todos.id == todo_id).first()
if not todo_model:
raise HTTPException(status_code=404, detail="Todo not found.")
# 按ID删除记录
db.query(models.Todos).filter(models.Todos.id == todo_id).delete()
db.commit()
测试效果:传入 todo_id=3,执行后返回 204,再查全量 Todo,ID=3 的记录已消失,删除成功!
自动生成的交互式API文档
启动服务后,访问 http://localhost:8000/docs,你会看到自动生成的交互式API文档:
- 每个接口都有详细的参数说明
- 可以直接在页面上测试API调用
- 实时显示请求示例和响应结果
- 修改代码后,实时同步
这比写Markdown文档实用多了,边开发边测试,效率翻倍。
为什么推荐新手用 FastAPI?3 个核心优势太香了
- 开发效率高:依赖注入 + 自动校验,少写 80% 重复代码;
- 调试方便:自动生成 Swagger UI,不用 Postman,浏览器就能测接口;
- 门槛低:Python 注解语法直观,新手容易理解,代码复制就能跑。
如果你是编程新手,想快速做出能落地的 API;或者想摆脱繁琐的参数校验、数据库连接管理,FastAPI 绝对是你的首选~
获取本章完整代码,请关注我的同名公众号「王二哥的技术笔记」,发送 【FastAPI 999】,代码直接复制就能跑。
关于 FastAPI 的其他疑问
“Python 核心技术”?有哪些?
如何系统学习 “FastAPI 开发实战” ?
剖析 “职场内外” 的真相?
相关内容我都给大家做好了,感兴趣的朋友来我主页找一找,直接就可以看到。
关注我,每天分享「Python」、「职场」有趣的实用干货,千万不要错过!