
上节说到:没有数据验证的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设计