路由与参数
这是什么:路由与参数 = 一个网址一个函数的基础上,让 URL 里携带信息:/items/5 里的 5、?skip=0&limit=10 里的分页值,都会自动变成函数参数。
为什么用:真实接口全是「带参」的:查第 3 页、找 id 为 42 的订单。FastAPI 从函数签名就能声明参数类型,非法值自动拦截——这正是它「签名即文档」的主场。
如何用:路径参数写进路由字符串、查询参数用带默认值的函数参数,本章顺手体验一次 422 自动校验。
路径参数:URL 的一部分
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
路由字符串里的 {item_id} 是占位符:访问 /items/5 时,FastAPI 把 5 取出来交给 item_id。关键在类型注解 int——它会被自动转换并校验:
GET /items/5 → {"item_id": 5} ✅ "5" 转成了整数 5
GET /items/abc → 422 错误 + 明细 ❌ "abc" 不是整数,自动拦截
不用手写 int()、不用手写 try/except——注解就是校验器,这就是第 1 章说的「类型注解在打工」。
查询参数:问号后面的键值对
不在路由里声明、函数签名里带默认值的参数,自动成为查询参数:
@app.get("/items")
def list_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
GET /items → {"skip": 0, "limit": 10} 全用默认值
GET /items?skip=20&limit=5 → {"skip": 20, "limit": 5} 自动转成 int
GET /items?skip=abc → 422 类型不对自动拦
?key=value&key2=value2 是 URL 标准写法(AJAX 教程里 GET 请求拼的就是它)。区分规则一句话:写在路由 {} 里的是路径参数,签名里带默认值的是查询参数。
两类参数混着用
@app.get("/users/{user_id}/posts")
def user_posts(user_id: int, tag: str = "all", only_first: bool = False):
return {"user_id": user_id, "tag": tag, "only_first": only_first}
GET /users/7/posts?tag=python&only_first=true
→ {"user_id": 7, "tag": "python", "only_first": True}
注意 bool 也支持:URL 里写 true / false(或 1 / 0),FastAPI 自动转成 Python 的 True / False。
async def 什么时候用
函数签名前加 async def 就是异步函数,适合里面有「等网络 / 等数据库」的异步操作(如 await 调用异步库)。入门阶段用普通 def 完全没问题——FastAPI 会自动把 def 路由丢进线程池,不阻塞服务。规则:用到异步库才写 async,拿不准就用 def。
记忆口诀:路由花括号装路径,签名默认值变查询;类型写对它把关门,写错直接 422。
❓ 常见问题
Q1:422 报错的响应长什么样?
{
"detail": [
{
"type": "int_parsing",
"loc": ["path", "item_id"],
"msg": "Input should be a valid integer, unable to parse string as an integer"
}
]
}
loc 告诉你哪个参数出错(path = 路径参数),msg 说明原因。这是自动校验的标配输出,看到 422 先读 detail。
Q2:路由 /items/{item_id} 和 /items/me 同时存在,访问谁?
两个都能注册。FastAPI 按声明顺序匹配:如果 /items/me 的路由写在前面,me 就走它;写在后面则会被 {item_id} 抢走(还因 me 转 int 失败报 422)。固定路径放前面,带参数的放后面。
Q3:忘了写类型注解会怎样?
def read_item(item_id) 没有 : int 时,参数被当成字符串处理,/items/5 拿到的是 "5"——不报错,但数学运算会炸。路径参数一定写注解,这是 FastAPI 的正确打开方式。
📝 本章小结
- 路径参数:路由里
{name}占位,配合类型注解自动转换与校验 - 查询参数:签名里带默认值的参数,
?a=1&b=2传入,bool也自动转 - 非法输入统一 422,
detail里带出错参数与原因 async def用于异步库场景;普通def不阻塞,入门放心用
动手改
- 给
read_item加一个查询参数verbose: bool = False,为 true 时多返回一个字段 - 写一个
/items/me路由,分别放在{item_id}前面和后面,体会匹配顺序 - 故意访问
/items/3.14,看看 422 的detail说什么
上一章:第一个应用 · 下一章:请求体与 Pydantic 🐸