路径参数(Path Parameters) 是 FastAPI 中最基础也最重要的概念之一。

🧩 一、什么是路径参数?

路径参数是从 URL 路径中提取的变量。

例如:

GET /users/123
GET /items/apple

其中 123apple 就是路径参数,分别代表用户 ID 和商品名称。


✅ 二、基本语法与示例

在 FastAPI 中,路径参数通过函数参数名与路径中的 {} 名称匹配

🔹 示例 1:简单路径参数

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}
  • 请求:GET /items/42
  • 响应:{"item_id": 42}
  • FastAPI 会自动将 "42" 转为 int 类型!
类型提示(Type Hint)会触发自动数据校验和转换!

🔹 示例 2:多个路径参数

@app.get("/users/{user_id}/orders/{order_id}")
def read_user_order(user_id: int, order_id: str):
    return {"user_id": user_id, "order_id": order_id}
  • 请求:GET /users/1001/orders/ORD-2025
  • 响应:{"user_id": 1001, "order_id": "ORD-2025"}
⚠️ 路径参数顺序不重要,名字必须和路径中的 {} 一致

🔹 示例 3:带类型校验(自动错误处理)

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}
  • 请求:GET /items/abc
  • 响应(自动返回 422 错误):

    {
      "detail": [
        {
          "loc": ["path", "item_id"],
          "msg": "value is not a valid integer",
          "type": "type_error.integer"
        }
      ]
    }
✅ 无需手动写 try-except!FastAPI 自动做数据验证 + 错误响应

⚠️ 三、重要注意事项(新手易错点)

1️⃣ 路径参数必须放在路径中,且用 {} 包裹

# ❌ 错误:没有 {},item_id 会被当作字面量
@app.get("/items/item_id")  

# ✅ 正确
@app.get("/items/{item_id}")

2️⃣ 函数参数名必须和 {} 中的名字完全一致

# ❌ 错误:名字不匹配
@app.get("/items/{item_id}")
def read_item(id: int):  # 参数名是 id,不是 item_id

# ✅ 正确
def read_item(item_id: int):

3️⃣ 路径匹配顺序很重要!更具体的路径要写在前面

# ❌ 危险:固定路径被当作路径参数
@app.get("/users/me")
def read_current_user():
    return {"user": "current"}

@app.get("/users/{user_id}")
def read_user(user_id: str):
    return {"user_id": user_id}

正确顺序:固定路径放前面!

@app.get("/users/me")          # 先匹配这个
def read_current_user():
    return {"user": "current"}

@app.get("/users/{user_id}")   # 再匹配这个
def read_user(user_id: str):
    return {"user_id": user_id}

否则,请求 /users/me 会被第二个路由捕获,user_id = "me",逻辑错误!


4️⃣ 路径参数默认是必需的(required)

  • 不能省略,也不能设默认值(除非用查询参数)
  • 如果需要可选,请改用 查询参数(Query Parameters)
# 路径参数不能有默认值 ❌
@app.get("/items/{item_id}")
def read_item(item_id: int = 0):  # 不推荐!语义不清

# 应该用查询参数 ✅
@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):
    ...

5️⃣ 支持任意类型(但需可从字符串转换)

FastAPI 使用 Pydantic 进行数据解析,支持:

类型示例
int, float自动转数字
str默认类型
UUID自动校验格式
datetime支持 ISO 8601 格式
自定义类需继承 BaseModel(一般用于请求体,非路径参数)
from uuid import UUID

@app.get("/posts/{post_id}")
def read_post(post_id: UUID):
    return {"post_id": str(post_id)}

请求:GET /posts/12345678-1234-5678-1234-567812345678 → 成功
请求:GET /posts/invalid → 自动返回 422 错误


🧪 四、完整可运行示例

# main.py
from fastapi import FastAPI
from uuid import UUID

app = FastAPI()

@app.get("/")
def home():
    return {"message": "Hello FastAPI!"}

@app.get("/users/me")
def read_current_user():
    return {"user": "the current user"}

@app.get("/users/{user_id}")
def read_user(user_id: str):
    return {"user_id": user_id}

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}

@app.get("/files/{file_path:path}")
def read_file(file_path: str):
    return {"file_path": file_path}

💡 最后一个例子用了 路径转换器(:path,允许路径中包含 /,比如:

  • 请求:GET /files/folder1/folder2/file.txt
  • file_path = "folder1/folder2/file.txt"