新手必看:FastAPI 参数接收的正确姿势(路径 / 查询 / 请求体全解析)
继上一篇《FastAPI 零基础入门:从安装到快速搭建 Web 接口》之后,本篇聚焦 FastAPI 最核心的参数接收能力 —— 路径参数、查询参数、请求体,用(大白话 + 实操代码 + 可视化测试)的方式拆解,新手跟着敲代码就能懂,掌握后就能实现真正的 “数据交互型接口”。
前言
上一篇我们学会了搭建基础接口和四种请求方法,但实际开发中,接口不可能只返回固定数据:比如根据用户 ID 查信息、分页查询列表、提交用户注册信息… 这些都需要前端给后端传数据,而 FastAPI 接收前端数据的核心方式就是路径参数、查询参数、请求体,这也是新手从 “写死数据” 到 “动态交互” 的关键一步。
前置准备
确保你已经完成:
- 安装 FastAPI 和 uvicorn(pip install fastapi uvicorn);
- 熟悉基础的 FastAPI 项目结构和启动方式;
- 保留上一篇的 main.py 文件,本篇代码都基于这个文件迭代。
1 路径参数:从URL路径中取数据
1.1.什么是路径参数?
简单来说:把参数直接写在接口URL的路径里,比如想根据用户ID查询信息,接口地址设计成/user/1(1就是用户ID),这个1就是路径参数。
核心场景:查询 / 操作;指定唯一资源(如用户 ID、商品 ID、文章 ID)。
1.2.基础实操:获取单个用户ID
打开main.py,编写如下代码:
fromfastapiimportFastAPIimportuvicorn app=FastAPI()# 路径参数核心语法:@app.get("/路径/{参数名}")@app.get("/user/{user_id}",summary="根据用户ID查询用户信息")defget_user_by_id(user_id:int):# 这里指定类型int,FastAPI会自动校验!# 模拟根据ID查数据(实际开发中可对接数据库)return{"code":200,"msg":"查询成功","data":{"user_id":user_id,# 直接使用路径参数"username":f"用户{user_id}","age":18+user_id%10# 简单动态生成年龄}}if__name__=='__main__':uvicorn.run("main:app",host="127.0.0.1",port=8000,reload=True)1.3.测试与关键知识点
第一步:启动服务
点击 PyCharm 运行按钮,启动 main.py,确保服务正常。
第二步:访问接口
打开浏览器,访问:http://127.0.0.1:8000/user/5
返回结果如下:
新手必看知识点:
- 类型注解的作用:如果访问http://127.0.0.1:8000/user/abc(传字符串),FastAPI 会自动返回 422 错误,无需手动写校验代码;
- 参数名要一致:装饰器里的{user_id}必须和函数参数user_id同名;
- 支持多种类型:除了 int,还支持 str、float、bool 等,比如/article/{article_title:str}。
2 查询参数:URL中?后面的键值对
2.1.什么是查询参数?
简单说:在 URL 末尾用?参数名=值的形式传参,多个参数用&分隔,比如/goods?page=1&size=10(page 是页码,size 是每页条数)。
核心场景:筛选、分页、模糊查询;(如列表分页、多条件筛选商品)
2.2. 基础实操:商品列表分页查询
代码如下:
fromfastapiimportFastAPIimportuvicorn app=FastAPI()# 查询参数:无需在路径中写,函数直接接收参数即可@app.get("/goods",summary="商品列表分页查询")defget_goods_list(page:int=1,# 默认值:如果前端不传,默认查第1页size:int=10# 默认值:如果前端不传,默认每页10条):# 模拟分页数据(实际开发中根据page和size查数据库)goods=[]foriinrange(size):goods.append({"goods_id":(page-1)*size+i+1,"goods_name":f"商品{(page-1)*size+i+1}","price":99.9+i})return{"code":200,"msg":"查询成功","data":{"page":page,"size":size,"total":100,# 模拟总条数"goods_list":goods}}if__name__=='__main__':uvicorn.run("main:app",host="127.0.0.1",port=8000,reload=True)2.3.测试与关键知识
- 不传参数:访问http://127.0.0.1:8000/goods,默认使用page=1&size=10;
- 传参数:访问http://127.0.0.1:8000/goods?page=2&size=5,返回第 2 页、每页 5 条数据;
返回结果:如图
新手必看知识点:
- 查询参数无需在路径中定义:函数参数直接写,FastAPI 会自动从 URL 的?后解析;
- 默认值的作用:前端不传参时使用默认值,避免报错;
- 混合使用:路径参数和查询参数可以一起用,比如/user/{user_id}/orders?page=1&size=10(根据用户 ID 查订单,同时分页)。
3 请求体:POST/PUT 请求传“大量数据”
3.1.什么是请求体?
简单说:前端把复杂数据(如注册信息、表单数据)放在请求的 “正文” 里传参,而不是 URL 里(URL 传参有长度限制)。
核心场景:提交 / 更新大量数据;(如用户注册、提交表单、上传复杂 JSON)。
⚠️ 注意:GET 请求不支持请求体,只能用 POST/PUT 等方法。
3.2.基础实操:用户注册(POST请求+请求体)
第一步:导入 Pydantic 模型(FastAPI 的 “数据校验神器”)
FastAPI 用 Pydantic 的BaseModel定义请求体的格式,自动校验数据类型和必填项,新手不用手动写校验逻辑。
第二步:编写注册接口代码
在 main.py 中新增如下代码:
fromfastapiimportFastAPIimportuvicornfrompydanticimportBaseModel# 导入Pydantic模型app=FastAPI()# 定义请求体模型:用户注册数据格式classUserRegister(BaseModel):username:str# 必填项:用户名(字符串)password:str# 必填项:密码(字符串)age:int=18# 可选项:年龄,默认18email:str# 可选项:邮箱,可传None# POST请求+请求体:用户注册@app.post("/user/register",summary="用户注册")defuser_register(user_info:UserRegister):# 接收请求体,类型为自定义的UserRegister# 模拟注册逻辑(实际开发中可写入数据库)return{"code":200,"msg":"注册成功","data":{"username":user_info.username,"age":user_info.age,"email":user_info.emailifuser_info.emailelse"未填写"}}if__name__=='__main__':uvicorn.run("main:app",host="127.0.0.1",port=8000,reload=True)3.3.测试请求体
请求体无法直接在浏览器访问,推荐用 FastAPI 自带的交互式文档测试:
- 启动服务后,访问http://127.0.0.1:8000/docs(自动生成的 Swagger 文档);
- 找到/user/register接口,点击「Try it out」;
- 编辑请求体 JSON(按模型格式填),示例:
- 点击 Execute,就能看到返回结果:
新手必看知识点:
- Pydantic 模型的作用:
- 自动校验:比如 age 传字符串会报错,username 不传会提示必填;
- 自动解析:把前端传的 JSON 自动转成 Python 对象,直接用user_info.username取值;
- 可选项定义:age: int = 18(默认值)、email: str | None = None(可传 None);
- 请求体只支持 POST/PUT 等:GET 请求不能用,因为 GET 请求没有 “正文”。
4 三者对比:一张表看懂用法场景
| 类型 | 传参位置 | 核心场景 | 请求方法支持 | 示例 |
|---|---|---|---|---|
| 路径参数 | URL 路径中(/user/{id}) | 唯一资源查询 / 操作(ID) | 所有方法 | /user/1、/goods/100 |
| 查询参数 | URL 末尾(?page=1&size=10) | 筛选、分页、简单条件查询 | 所有方法(GET 常用) | /goods?page=2&size=5 |
| 请求体 | 请求正文(JSON) | 提交 / 更新大量复杂数据 | POST/PUT/ 等 | 注册、提交表单、修改多字段 |
5 新手避坑指南
- 参数名大小写敏感:路径参数{user_id}和函数参数user_id必须完全一致;
- 类型注解别漏写:FastAPI 靠类型注解做自动校验,漏写会失去校验能力;
- GET 请求别用请求体:前端用 GET 传请求体,后端收不到,这是 HTTP 协议规定;
- 测试工具选对:路径参数 / 查询参数用浏览器,请求体用/docs或 Postman。
6 进阶美化!Path/Query/Field 让参数更规范
这是最简单、最实用的进阶用法,不用改逻辑,只需要加一行代码,就能让你的接口:
- 带中文注释
- 加参数校验(比如数字必须大于 0)
- 接口文档更清晰
- 一看就懂每个参数干嘛用
先安装/导入(必须做)
fromfastapiimportFastAPI,Path,Query# 路径+查询参数专用frompydanticimportBaseModel,Field# 请求体专用6.1.路径参数+Path
作用:给路径参数加说明、限制范围
@app.get("/user/{user_id}")defget_user(# Path:给路径参数加注释 + 校验user_id:int=Path(...,description="用户ID,必须大于0",ge=1)):return{"user_id":user_id}…代表必填;ge=1代表必须 ≥ 1;description接口文档里会显示中文说明
6.2.查询参数+Query
作用:给查询参数加默认值、长度限制、范围限制
@app.get("/goods")defget_goods(page:int=Query(1,description="页码",ge=1),size:int=Query(10,description="每页数量",le=100)):return{"page":page,"size":size}ge=1大于等于 1;le=100小于等于 100;不传就用默认值,传了自动校验
6.3.请求体+Field
作用:给请求体字段加说明、长度 / 格式校验
classUserRegister(BaseModel):username:str=Field(...,description="用户名,必填")password:str=Field(...,description="密码,至少6位",min_length=6)age:int=Field(18,description="年龄,默认18")@app.post("/user/register")defregister(user:UserRegister):returnusermin_length=6密码最少 6 位;自动校验,不合格直接报错
三者一起用(最常用实战写法)
@app.get("/user/{user_id}/order")defget_user_order(# 路径参数user_id:int=Path(...,description="用户ID",ge=1),# 查询参数page:int=Query(1,description="页码")):return{"user_id":user_id,"page":page}总结
本篇我们掌握了 FastAPI接收前端数据的三种核心方式以及接口参数的完整用法:
路径参数:从 URL 路径取唯一标识;用Path获取 URL 路径中的唯一标识,支持校验与文档说明;
查询参数:从 URL 末尾取筛选 / 分页条件用Query获取 URL 问号后的筛选、分页条件,可设默认值与限制;
请求体:从请求正文取复杂数据(配合 Pydantic 自动校验)。用BaseModel + Field接收复杂 JSON 数据,自动完成格式校验与字段约束。
三者搭配使用,就能覆盖绝大多数接口传参场景,让接口更规范、更健壮、文档更清晰。新手跟着代码实操一遍,并用 /docs 测试验证,就能完全掌握“前端传参、后端接收”的核心逻辑。下一篇我们将继续讲解响应模型、统一异常处理、依赖注入等实战内容,帮你写出生产级标准接口。
