10分钟搞定FastAPI中“数据库连接管理、参数校验、文档维护”三大核心难题,让新手也能轻松地写出可落地的API

24 阅读7分钟

fHtEHLtC1

你是不是也遇到过这样的崩溃时刻?

只想写个简单的 API 接口,却被数据库连接搞得头大 —— 打开了忘关闭,关早了查不到数据;

实现参数验证时,一堆 if-else 绕到头晕;

接口文档还要单独维护,改完代码又得同步更新...;

作为编程新手,只想快速实现「增删改查」全功能 API 接口,怎么这么难吗?”

别急!今天用 FastAPI + SQLAlchemy 手把手教你实现「增删改查」全功能 API 接口。10 分钟搞定数据库连接管理、API 参数验证、自动生成文档需求。

代码直接复制就能跑,新手也能轻松上手~

先明确:API 开发的 3 大痛点,我们要怎么解决?

做接口开发,新手最容易卡壳的 3 个问题:

  1. 数据库连接混乱:手动管理数据库连接开关易遗漏,导致资源占用;
  2. 参数验证繁琐:请求体、路径参数要挨个判断合法性,代码冗余;
  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")

关键亮点

  1. Path(gt=0):强制 todo_id 必须大于 0,无效参数直接返回 422 错误,不用手动判断;
  2. 请求成功,明确返回 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文档

  1. 每个接口都有详细的参数说明
  2. 可以直接在页面上测试API调用
  3. 实时显示请求示例和响应结果
  4. 修改代码后,实时同步

这比写Markdown文档实用多了,边开发边测试,效率翻倍

为什么推荐新手用 FastAPI?3 个核心优势太香了

  1. 开发效率高:依赖注入 + 自动校验,少写 80% 重复代码;
  2. 调试方便:自动生成 Swagger UI,不用 Postman,浏览器就能测接口;
  3. 门槛低:Python 注解语法直观,新手容易理解,代码复制就能跑。

如果你是编程新手,想快速做出能落地的 API;或者想摆脱繁琐的参数校验、数据库连接管理,FastAPI 绝对是你的首选~

获取本章完整代码,请关注我的同名公众号「王二哥的技术笔记」,发送 【FastAPI 999】,代码直接复制就能跑。

关于 FastAPI 的其他疑问

“Python 核心技术”?有哪些?

如何系统学习 “FastAPI 开发实战” ?

剖析 “职场内外” 的真相?

相关内容我都给大家做好了,感兴趣的朋友来我主页找一找,直接就可以看到。

关注我,每天分享「Python」、「职场」有趣的实用干货,千万不要错过!