别再堆if-else验参数了!FastAPI自带的参数验证器,至少省一半调试时间

你是不是也遇到过这样的场景------用户传了个 book_id=-1,接口直接崩了?或者查询评分时塞进来一个 rating=999,数据库默默吐出所有内容?

没验证的参数,就像没锁的门。

上一期文章中,我们学习了如何使用 Pydantic 对请求体进行数据验证。今天,我们将深入探讨FastAPI的另外两种重要验证方式:路径参数验证查询参数验证

访问上一篇文章,请点击:跳转

为什么需要验证路径和查询参数?

当我们构建RESTful API时,除了请求体数据,路径参数和查询参数同样需要严格的验证:

路径参数 :如/books/{book_id}中的book_id

查询参数 :如/books?rating=5中的rating

没有验证的参数就像没有安检的入口,可能导致各种安全问题和非预期行为。

路径参数验证:精准控制资源访问

问题场景分析:以图书查询接口为例

python 复制代码
@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

这个接口会存在两个问题:

  1. 书籍不存在时,返回None,用户体验不是很好。
  2. 没有对book_id参数进行合法性验证(如负数、零值)

解决方案:使用Path进行验证

python 复制代码
from fastapi import Path

@app.get("/books/{book_id}")
async def read_book(book_id: int = Path(gt=0)):
    for book in BOOKS:
        if book.id == book_id:
            return book
    return {"error": "Book not found"}

关键改进:

  1. Path(gt=0) 确保 book_id 参数必须大于 0。
  2. 当书籍不存在时,给用户返回明确的错误提示。

验证效果展示

回到浏览器的 Swagger UI 页面,刷新页面。我们进入 GET /books/{book_id} 接口,传入 book_id=0

FastAPI自动返回422错误,及如下异常响应信息:

json 复制代码
{
  "detail": [
    {
      "type": "greater_than",
      "loc": [
        "path",
        "book_id"
      ],
      "msg": "Input should be greater than 0",
      "input": "0",
      "ctx": {
        "gt": 0
      }
    }
  ]
}

从错误信息中,用户就可以明确的了解到,我们传入的 book_id 参数必须大于 0。

删除接口做同步优化

python 复制代码
@app.delete("/books/{book_id}")
async def delete_book(book_id: int = Path(gt=0)):
    for i in range(len(BOOKS)):
        if BOOKS[i].id == book_id:
            BOOKS.pop(i)
            break

查询参数验证:确保筛选条件的合理性

问题场景分析:图书按评分查询接口为例

python 复制代码
@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

存在的问题:评分范围并没有做限制(如,可能会传入0或6)

解决方案:使用Query进行验证

python 复制代码
from fastapi import Query

@app.get("/books/")
async def read_books_by_rating(book_rating: int = Query(gt=0, lt=6)):
    books_to_return = []
    for book in BOOKS:
        if book.rating == book_rating:
            books_to_return.append(book)
    return books_to_return

验证规则说明:

gt=0:必须大于 0 lt=6:必须小于 6

综合效果:只允许1-5的整数评分

验证效果展示

回到浏览器的 Swagger UI 页面,刷新页面。我们进入 GET /books/ 接口,传入 book_rating=0

FastAPI自动返回422错误,及如下异常响应信息:

json 复制代码
{
  "detail": [
    {
      "type": "greater_than",
      "loc": [
        "query",
        "book_rating"
      ],
      "msg": "Input should be greater than 0",
      "input": "0",
      "ctx": {
        "gt": 0
      }
    }
  ]
}

从错误信息中,用户就可以明确的了解到,我们传入的 book_rating 参数必须大于 0。

Path 与 Query 验证的对比

特性 Path 参数验证 Query 参数验证
使用场景 资源标识(如ID) 筛选条件(如评分、分类)
导入方式 from fastapi import Path from fastapi import Query
语法示例 book_id: int = Path(gt=0) rating: int = Query(gt=0, lt=6)
验证重点 确保资源标识的合法性 确保查询条件的合理性

最佳实践

  1. 始终验证:对所有输入参数进行验证,不信任任何外部输入
  2. 明确范围:为数值参数设置合理的上下限
  3. 统一错误处理:保持错误响应格式的一致性
  4. 文档完善:良好的验证规则会自动体现在API文档中

下节预告

掌握了这些基础验证后,下一期我们将深入探讨 FastAPI 中常用状态码和 HTTP 异常的实现,让你的 API 更加标准和专业。

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


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

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

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


点赞 :支持技术分享!

分享 :分享给身边感兴趣的朋友!

关注我 :获取更多FastAPI实战技巧!


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

相关推荐
玄同7654 小时前
从 0 到 1:用 Python 开发 MCP 工具,让 AI 智能体拥有 “超能力”
开发语言·人工智能·python·agent·ai编程·mcp·trae
小瑞瑞acd4 小时前
【小瑞瑞精讲】卷积神经网络(CNN):从入门到精通,计算机如何“看”懂世界?
人工智能·python·深度学习·神经网络·机器学习
闲人编程5 小时前
使用FastAPI和WebSocket构建高性能实时聊天系统
websocket·网络协议·网络编程·fastapi·持久化·实时聊天·codecapsule
火车叼位5 小时前
也许你不需要创建.venv, 此规范使python脚本自备依赖
python
火车叼位5 小时前
脚本伪装:让 Python 与 Node.js 像原生 Shell 命令一样运行
运维·javascript·python
孤狼warrior5 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Katecat996635 小时前
YOLO11分割算法实现甲状腺超声病灶自动检测与定位_DWR方法应用
python
玩大数据的龙威6 小时前
农经权二轮延包—各种地块示意图
python·arcgis
ZH15455891316 小时前
Flutter for OpenHarmony Python学习助手实战:数据库操作与管理的实现
python·学习·flutter
belldeep6 小时前
python:用 Flask 3 , mistune 2 和 mermaid.min.js 10.9 来实现 Markdown 中 mermaid 图表的渲染
javascript·python·flask