FastAPI 入门教程FastAPI 入门教程
首页
基础教程
实战项目
FastAPI官网
首页
基础教程
实战项目
FastAPI官网
  • 基础教程

    • 📚 基础教程
    • 第0章 - Python 快速入门
    • 第1章 - FastAPI 简介
    • 第2章 - 环境搭建
    • 第3章 - 第一个 API
    • 第4章 - 路径参数
    • 第5章 - 查询参数
    • 第6章 - 请求体
    • 第7章 - 响应模型
    • 第8章 - CRUD 操作
    • 第9章 - 数据库操作

第4章 - 路径参数

嗨,朋友!我是长安。

这一章我来讲讲路径参数。这是我当年学习的时候觉得特别实用的一个功能,几乎每个接口都会用到!

🎯 本章目标

  • 理解什么是路径参数
  • 学会定义和使用路径参数
  • 掌握路径参数的类型验证
  • 学会使用枚举限制参数值

1️⃣ 什么是路径参数?

路径参数就是 URL 路径中的变量部分。举个例子你就懂了:

比如:

  • /users/1 - 获取 ID 为 1 的用户
  • /users/2 - 获取 ID 为 2 的用户
  • /products/abc123 - 获取编号为 abc123 的商品

这里的 1、2、abc123 就是路径参数。

2️⃣ 定义路径参数

使用 {参数名} 的方式在路径中定义参数:

from fastapi import FastAPI

app = FastAPI()

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

访问 http://127.0.0.1:8000/users/123,返回:

{"user_id": "123"}

长安提醒

默认情况下,路径参数是字符串类型! 这是很多新手容易忽略的地方,我当年也踩过坑。

3️⃣ 指定��数类型

通过类型注解指定参数类型,FastAPI 会自动进行类型转换和验证:

@app.get("/users/{user_id}")
def get_user(user_id: int):  # 指定为 int 类型
    return {"user_id": user_id, "type": type(user_id).__name__}

访问 http://127.0.0.1:8000/users/123,返回:

{"user_id": 123, "type": "int"}

类型验证

如果传入的参数不能转换为指定类型,FastAPI 会自动返回错误:

访问 http://127.0.0.1:8000/users/abc,返回:

{
    "detail": [
        {
            "type": "int_parsing",
            "loc": ["path", "user_id"],
            "msg": "Input should be a valid integer, unable to parse string as an integer",
            "input": "abc"
        }
    ]
}

4️⃣ 常用参数类型

from fastapi import FastAPI

app = FastAPI()

# 整数类型
@app.get("/items/{item_id}")
def get_item(item_id: int):
    return {"item_id": item_id}

# 字符串类型
@app.get("/users/{username}")
def get_user(username: str):
    return {"username": username}

# 浮点数类型
@app.get("/prices/{price}")
def get_price(price: float):
    return {"price": price}

# 布尔类型
@app.get("/status/{is_active}")
def get_status(is_active: bool):
    return {"is_active": is_active}

布尔类型的特殊处理

FastAPI 对布尔类型很智能,以下值都会被识别为 True:

  • true、True、TRUE
  • 1
  • yes、Yes、YES
  • on、On、ON

以下值会被识别为 False:

  • false、False、FALSE
  • 0
  • no、No、NO
  • off、Off、OFF
# 访问 /status/true  -> {"is_active": true}
# 访问 /status/yes   -> {"is_active": true}
# 访问 /status/1     -> {"is_active": true}
# 访问 /status/false -> {"is_active": false}
# 访问 /status/no    -> {"is_active": false}

5️⃣ 多个路径参数

可以定义多个路径参数:

@app.get("/users/{user_id}/posts/{post_id}")
def get_user_post(user_id: int, post_id: int):
    return {
        "user_id": user_id,
        "post_id": post_id
    }

访问 http://127.0.0.1:8000/users/1/posts/100,返回:

{"user_id": 1, "post_id": 100}

6️⃣ 路径顺序很重要!

长安的重要提醒

路径的定义顺序非常非常重要!FastAPI 会按顺序匹配路径。 这是我当年花了好几个小时才找到的坑,你一定要注意!

# ❌ 错误示例
@app.get("/users/{user_id}")
def get_user(user_id: str):
    return {"user_id": user_id}

@app.get("/users/me")  # 这个永远不会被匹配到!
def get_current_user():
    return {"user": "当前用户"}

因为 /users/me 会先被 /users/{user_id} 匹配,me 会被当作 user_id。

# ✅ 正确示例
@app.get("/users/me")  # 固定��径放前面
def get_current_user():
    return {"user": "当前用户"}

@app.get("/users/{user_id}")  # 动态路径放后面
def get_user(user_id: str):
    return {"user_id": user_id}

7️⃣ 使用枚举限制参数值

有时候我们希望参数只能是特定的几个值,可以使用枚举:

from enum import Enum
from fastapi import FastAPI

app = FastAPI()

# 定义枚举类
class Gender(str, Enum):
    male = "male"
    female = "female"
    other = "other"

@app.get("/users/gender/{gender}")
def get_users_by_gender(gender: Gender):
    return {"gender": gender, "message": f"获取性别为 {gender.value} 的用户"}

现在 gender 参数只能是 male、female 或 other:

  • 访问 /users/gender/male ✅
  • 访问 /users/gender/female ✅
  • 访问 /users/gender/abc ❌ 返回错误

枚举的好处

  1. 自动验证 - 只接受定义的值
  2. 文档清晰 - 在 Swagger UI 中会显示可选值
  3. 代码提示 - IDE 会提示可用的值

更多枚举示例

from enum import Enum

# 订单状态
class OrderStatus(str, Enum):
    pending = "pending"      # 待支付
    paid = "paid"            # 已支付
    shipped = "shipped"      # 已发货
    delivered = "delivered"  # 已送达
    cancelled = "cancelled"  # 已取消

@app.get("/orders/status/{status}")
def get_orders_by_status(status: OrderStatus):
    return {"status": status.value}

# 文章分类
class Category(str, Enum):
    tech = "tech"
    life = "life"
    travel = "travel"

@app.get("/articles/category/{category}")
def get_articles(category: Category):
    return {"category": category.value}

8️⃣ 使用 Path 进行更多验证

使用 Path 可以对路径参数进行更详细的验证:

from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
def get_item(
    item_id: int = Path(
        title="商品ID",
        description="商品的唯一标识符",
        ge=1,        # 大于等于 1
        le=10000,    # 小于等于 10000
        example=42   # 示例值
    )
):
    return {"item_id": item_id}

Path 的常用参数

参数说明示例
title参数标题title="用户ID"
description参数描述description="用户的唯一标识"
ge大于等于ge=1
gt大于gt=0
le小于等于le=100
lt小于lt=100
example示例值example=42

字符串长度验证

@app.get("/users/{username}")
def get_user(
    username: str = Path(
        min_length=3,   # 最小长度
        max_length=20,  # 最大长度
        pattern="^[a-zA-Z0-9_]+$"  # 正则表达式
    )
):
    return {"username": username}

9️⃣ 完整示例

from enum import Enum
from fastapi import FastAPI, Path

app = FastAPI(title="路径参数示例")

# 用户角色枚举
class UserRole(str, Enum):
    admin = "admin"
    user = "user"
    guest = "guest"

# 模拟数据
fake_users = {
    1: {"id": 1, "name": "张三", "role": "admin"},
    2: {"id": 2, "name": "李四", "role": "user"},
    3: {"id": 3, "name": "王五", "role": "guest"},
}

@app.get("/")
def home():
    return {"message": "路径参数示例"}

# 基本路径参数
@app.get("/users/{user_id}", tags=["用户"])
def get_user(user_id: int):
    """根据ID获取用户"""
    if user_id in fake_users:
        return fake_users[user_id]
    return {"error": "用户不存在"}

# 使用 Path 验证
@app.get("/items/{item_id}", tags=["商品"])
def get_item(
    item_id: int = Path(
        title="商品ID",
        description="商品的唯一标识符,范围1-9999",
        ge=1,
        le=9999,
        example=100
    )
):
    """获取商品信息"""
    return {"item_id": item_id, "name": f"商品{item_id}"}

# 使用枚举
@app.get("/users/role/{role}", tags=["用户"])
def get_users_by_role(role: UserRole):
    """根据角色获取用户"""
    result = [u for u in fake_users.values() if u["role"] == role.value]
    return {"role": role.value, "users": result}

# 多个路径参数
@app.get("/departments/{dept_id}/employees/{emp_id}", tags=["部门"])
def get_employee(dept_id: int, emp_id: int):
    """获取部门下的员工"""
    return {
        "department_id": dept_id,
        "employee_id": emp_id
    }

# 固定路径优先
@app.get("/articles/latest", tags=["文章"])
def get_latest_article():
    """获取最新文章"""
    return {"title": "最新文章", "id": 999}

@app.get("/articles/{article_id}", tags=["文章"])
def get_article(article_id: int):
    """根据ID获取文章"""
    return {"id": article_id, "title": f"文章{article_id}"}

📝 小结

本章我们学习了:

  1. ✅ 路径参数的定义方式 {param}
  2. ✅ 类型注解和自动验证
  3. ✅ 多个路径参数
  4. ✅ 路径顺序的重要性
  5. ✅ 使用枚举限制参数值
  6. ✅ 使用 Path 进行详细验证

🏃 下一步

路径参数学会了,但有时候我们需要传递可选参数,比如分页、排序等。下一章学习查询参数!

👉 第5章 - 查询参数

💪 练习题

  1. 创建一个接口 /products/{product_id},要求 product_id 必须是 1-1000 之间的整数

  2. 创建一个订单状态枚举,包含:pending、processing、completed、cancelled,然后创建接口 /orders/status/{status} 根据状态查询订单

  3. 创建接口 /categories/{category_id}/products/{product_id},获取某分类下的某商品

参考答案
from enum import Enum
from fastapi import FastAPI, Path

app = FastAPI()

# 练习1
@app.get("/products/{product_id}")
def get_product(
    product_id: int = Path(ge=1, le=1000)
):
    return {"product_id": product_id}

# 练习2
class OrderStatus(str, Enum):
    pending = "pending"
    processing = "processing"
    completed = "completed"
    cancelled = "cancelled"

@app.get("/orders/status/{status}")
def get_orders(status: OrderStatus):
    return {"status": status.value, "orders": []}

# 练习3
@app.get("/categories/{category_id}/products/{product_id}")
def get_category_product(category_id: int, product_id: int):
    return {
        "category_id": category_id,
        "product_id": product_id
    }
最近更新: 2025/12/26 11:25
Contributors: 王长安
Prev
第3章 - 第一个 API
Next
第5章 - 查询参数