FastAPI 中,客户端向服务端传递数据主要通过两种参数:路径参数(Path Parameters)和查询参数(Query Parameters)。路径参数是 URL 路径的一部分,通常用于标识资源;查询参数跟在 ? 后面,常用于过滤、排序等可选条件。下面逐一讲解。
路径参数
路径参数写在 URL 路径中,使用 {} 占位,函数参数名与之对应即可。
基本用法
1 2 3 4 5 6 7
| from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}") async def get_user(user_id: int): return {"user_id": user_id}
|
访问 /users/42 时,user_id 会自动转为 int 类型。如果传入非数字如 /users/abc,FastAPI 会自动返回 422 校验错误。
类型校验
FastAPI 会根据类型注解自动做类型转换和校验:
1 2 3 4
| @app.get("/items/{item_id}") async def get_item(item_id: int): return {"item_id": item_id, "type": type(item_id).__name__}
|
支持的类型包括 int、float、str、bool、UUID 等。
路径参数的顺序
注意:固定路径必须定义在动态路径之前,否则会被动态路径拦截:
1 2 3 4 5 6 7 8 9 10
| @app.get("/users/me") async def get_current_user(): return {"username": "admin"}
@app.get("/users/{user_id}") async def get_user(user_id: int): return {"user_id": user_id}
|
使用 Path 做额外校验
1 2 3 4 5 6 7 8 9 10 11 12 13
| from fastapi import Path
@app.get("/articles/{article_id}") async def get_article( article_id: int = Path( ..., title="文章ID", description="要获取的文章编号", ge=1, le=10000, ) ): return {"article_id": article_id}
|
Path 常用校验参数:
| 参数 |
说明 |
... |
必填(省略号) |
ge / gt |
大于等于 / 大于 |
le / lt |
小于等于 / 小于 |
min_length / max_length |
字符串最小/最大长度 |
regex |
正则匹配(FastAPI 旧版) |
pattern |
正则匹配(Pydantic v2) |
title / description |
文档展示用 |
枚举类型的路径参数
1 2 3 4 5 6 7 8 9 10 11
| from enum import Enum
class CategoryEnum(str, Enum): tech = "tech" life = "life" travel = "travel"
@app.get("/posts/{category}") async def get_posts(category: CategoryEnum): return {"category": category}
|
访问 /posts/tech 正常返回;访问 /posts/music 返回 422。
查询参数
查询参数是 URL 中 ? 后面的键值对,如 ?page=1&size=20。FastAPI 中,函数参数不在路径中且不是 Body 类型,就会被自动识别为查询参数。
基本用法
1 2 3
| @app.get("/posts") async def list_posts(page: int = 1, size: int = 10): return {"page": page, "size": size}
|
访问 /posts?page=2&size=5,page=2, size=5;不传参数则使用默认值。
可选查询参数
1 2 3 4 5 6 7 8 9 10 11
| from typing import Optional
@app.get("/search") async def search( keyword: Optional[str] = None, category: Optional[str] = None, ): result = {"keyword": keyword, "category": category} if keyword: result["match"] = f"搜索: {keyword}" return result
|
Optional[str] = None 表示该参数可选,不传时为 None。
使用 Query 做额外校验
1 2 3 4 5 6 7 8 9
| from fastapi import Query
@app.get("/items") async def list_items( offset: int = Query(default=0, ge=0, description="偏移量"), limit: int = Query(default=10, ge=1, le=100, description="每页数量"), sort: Optional[str] = Query(default=None, pattern=r"^(asc|desc)$", description="排序方式"), ): return {"offset": offset, "limit": limit, "sort": sort}
|
Query 支持与 Path 几乎相同的校验参数。
接收多个同名查询参数
1 2 3 4 5 6 7 8 9
| from typing import List
@app.get("/filter") async def filter_items(tags: List[str] = Query(default=[])): """ 示例: /filter?tags=python&tags=fastapi&tags=web 结果: tags = ["python", "fastapi", "web"] """ return {"tags": tags}
|
布尔类型查询参数
1 2 3 4 5 6 7 8 9 10
| @app.get("/products") async def list_products(in_stock: bool = False): """ 访问: /products?in_stock=true → True /products?in_stock=1 → True /products?in_stock=yes → True /products?in_stock=on → True /products → False(默认值) """ return {"in_stock": in_stock}
|
路径参数与查询参数的组合
最常见的场景是路径参数标识资源,查询参数做筛选:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @app.get("/users/{user_id}/posts") async def get_user_posts( user_id: int = Path(..., ge=1), page: int = Query(default=1, ge=1), size: int = Query(default=20, ge=1, le=100), status: Optional[str] = Query(default=None, pattern=r"^(draft|published|archived)$"), ): """ 获取某个用户的文章列表
- **user_id**: 用户ID(路径参数) - **page**: 页码(查询参数,默认第1页) - **size**: 每页数量(查询参数,默认20,最大100) - **status**: 文章状态过滤(可选) """ return { "user_id": user_id, "page": page, "size": size, "status": status, }
|
请求示例:/users/42/posts?page=2&size=5&status=published
小结
| 特性 |
路径参数 |
查询参数 |
| 位置 |
URL 路径中 /users/{id} |
URL ? 后面 ?key=val |
| 用途 |
标识资源 |
过滤、排序、分页 |
| 必填 |
默认必填 |
默认可选 |
| 校验工具 |
Path() |
Query() |
| 类型 |
str / int / UUID / Enum |
str / int / bool / List 等 |
掌握路径参数和查询参数是 FastAPI 开发的基础,配合 Path 和 Query 的校验能力,可以在不写额外逻辑的情况下完成大部分参数校验工作,并自动生成清晰的 API 文档。