这份数据验证方案,可以让你的 FastAPI 崩溃率直降90%

上节说到:没有数据验证的API,就像没有保安的小区,什么"妖魔鬼怪"都能随便进出。

今天,我将通过构建一个"图书管理API"的实战案例,带你掌握用 FastAPI + Pydantic 打造"坚固" 后端服务的核心技巧,让你的接口从此告别脏数据的困扰!

数据验证:为API穿上"防弹衣"

为什么需要自动验证?

在传统开发中,我们需要写大量的if-else来判断数据合法性:

python 复制代码
if not isinstance(id, int):
    return {"error": "ID必须是整数"}
if rating < 1 or rating > 5:
    return {"error": "评分必须在1-5之间"}
# ...更多繁琐的判断

Pydantic 让这一切变得优雅、简单

上一小节中,我们构建了一个 BodyRequest(BaseModel) 对象。使用 Pydantic 给我们做一些自动化的检查。

python 复制代码
class BodyRequest(BaseModel):
    id: int
    title: str
    author: str
    description: str
    rating: int

今天,我们在这此基础上,使用 Pydantic 对每个字段添加自定义的数据验证。

python 复制代码
class BodyRequest(BaseModel):
    id: Optional[int] = Field(description="ID is not needed on create", default=None)
    title: str = Field(min_length=3)
    author: str = Field(min_length=1)
    description: str = Field(min_length=1, max_length=100)
    rating: int = Field(gt=0, lt=6)

我们回到浏览器的 Swagger UI 页面,刷新页面。我们进入 POST /create_book 接口,在请求体中使用如下内容,点击 "Execute",执行它。

json 复制代码
{
  "id": 0,
  "title": "",
  "author": "string",
  "description": "string",
  "rating": 1
}

**效果立竿见影:**当传入非法数据时,Pydantic 自动返回清晰的错误信息,HTTP状态码422(验证失败):

完整CRUD实战:从创建到删除

1、创建(Create)
python 复制代码
@app.post("/create_book")
async def create_book(book_reqeust: BodyRequest):
    new_book = Book(**book_reqeust.model_dump())
    BOOKS.append(find_book_id(new_book))
    return {"message": "图书创建成功!"}


def find_book_id(book: Book) -> Book:
    if len(BOOKS) > 0:
        book.id = BOOKS[-1].id + 1
    else:
        book.id = 1
    return book
2、查询(Read)
python 复制代码
# 按ID查询单本书
@app.get("/books/{book_id}")
async def read_book(book_id: int):
    for book in BOOKS:
        if book.id == book_id:
            return book
    return None


# 按评分查询书籍列表  
@app.get("/books/")
async def read_books_by_rating(book_rating: int):
    books_to_return = []
    for book in BOOKS:
        if book.rating == book_rating:
            books_to_return.append(book)
    return books_to_return
3、更新(Update)
python 复制代码
@app.put("/books/update_book")
async def update_book(updated_book: BodyRequest):
    for i in range(len(BOOKS)):
        if BOOKS[i].id == updated_book.id:
            BOOKS[i] = updated_book
            break
4、删除(Delete)
python 复制代码
@app.delete("/books/{book_id}")
async def delete_book(book_id: int):
    for i in range(len(BOOKS)):
        if BOOKS[i].id == book_id:
            BOOKS.pop(i)
            break

进阶技巧:巧用API文档

我们在前面已经对 BodyRequest(BaseModel) 的每个字段进行的自定义验证。

切回 Swagger UI 页面,找到 POST /create_book 接口,打开它。找到 "Request body" 下的 "Example Value" 。显然 "Example Value" 下的示例数据还是比较"简陋"的,如果线上使用的话不太合适。

现在,我们在 BodyRequest(BaseModel) 添加 model_config配置:

python 复制代码
class BodyRequest(BaseModel):
    id: Optional[int] = Field(description="ID is not needed on create", default=None)
    title: str = Field(min_length=3)
    author: str = Field(min_length=1)
    description: str = Field(min_length=1, max_length=100)
    rating: int = Field(gt=0, lt=6)
	# 新加内容
    model_config = {
        "json_schema_extra": {
            "example": {
                "title": "A new book",
                "author": "Mr.Wang",
                "description": "A new description of a book",
                "rating": 5
            }
        }
    }

回到浏览器的 Swagger UI 页面,刷新页面。找到 POST /create_book 接口,打开它。找到 "Request body" 下的 "Example Value" 内容如下:

可以看到 "Example Value" 的内容已经改变了。这回看着就比较专业了。

再回到浏览器的 Swagger UI 页面,找到 POST /create_book 接口,打开它。找到 "Request body" 下的 "Schema",点击它。

在这里,我们可以清晰的看到 "Request body" 中每个参数的验证类型和约束。这样,更方便前端测试。

写在最后

在本小节中,我们使用 Pydantic 完成繁琐的验证工作。

良好的类型提示,自动生成了API文档,彻底告别"代码写完还要写文档"的痛苦。

并且,在数据进入业务逻辑前就进行了验证,避免脏数据污染系统。

下节预告

本节中,我们在 BodyRequest(BaseModel) 中添加了类型验证和自定义验证。

但是,有些 API 接口并不使用 BodyRequest(BaseModel) ,那这些接口,我们应该如何完成我们验证需求呢?

欢迎 "关注",我们在下一小节一起来解锁这个问题。


-------- 写在最后 --------

关注我,每天1分钟,轻松懂 Python

我的同名公众号正在连载《FastAPI 开发实战》、《Python 核心技术》、《职场》。


点赞 :如果觉得有收获,点赞支持一下吧!

分享 :分享给身边同样对Python感兴趣的朋友!

关注我 :不要错过每一篇 Python 实战内容!


#Python #FastAPI #API #Web开发 #程序员 #编程教程 #效率提升 #后端开发 #API设计

相关推荐
不解风水9 分钟前
《深度学习入门:基于 Python 的理论与实现》(斋藤康毅)
人工智能·python·深度学习
偷星星的贼1115 分钟前
数据分析与科学计算
jvm·数据库·python
Blossom.1181 小时前
AI Agent智能办公助手:从ChatGPT到真正“干活“的系统
人工智能·分布式·python·深度学习·神经网络·chatgpt·迁移学习
应用市场1 小时前
Adam优化器深度解析:从数学原理到PyTorch源码实
人工智能·pytorch·python
a努力。1 小时前
2026 AI 编程终极套装:Claude Code + Codex + Gemini CLI + Antigravity,四位一体实战指南!
java·开发语言·人工智能·分布式·python·面试
梦茹^_^1 小时前
flask框架(笔记一次性写完)
redis·python·flask·cookie·session
二川bro1 小时前
Java集合类框架的基本接口有哪些?
java·开发语言·python
抠头专注python环境配置1 小时前
解决“No module named ‘tensorflow‘”报错:从导入失败到环境配置成功
人工智能·windows·python·tensorflow·neo4j
zhangfeng11331 小时前
PowerShell 中不支持激活你选中的 Python 虚拟环境,建议切换到命令提示符(Command Prompt)
开发语言·python·prompt
qh0526wy1 小时前
WINDOWS BAT 开机登录后自动启动
windows·python