路径参数¶
你可以使用与 Python 格式化字符串相同的语法来声明路径“参数”或“变量”。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
路径参数 item_id 的值将作为参数 item_id 传递给你的函数。
因此,如果你运行此示例并访问 http://127.0.0.1:8000/items/foo,你将看到如下响应:
{"item_id":"foo"}
带类型的路径参数¶
你可以使用标准 Python 类型注解在函数中声明路径参数的类型。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
在此例中,item_id 被声明为 int 类型。
提示
这将为你提供函数内部的编辑器支持,包括错误检查、补全等功能。
数据 转换¶
如果你运行此示例并打开浏览器访问 http://127.0.0.1:8000/items/3,你将看到如下响应:
{"item_id":3}
提示
请注意,你的函数接收(并返回)的值是 3,这是一个 Python int,而不是字符串 "3"。
因此,通过该类型声明,FastAPI 为你提供了自动请求 “解析”。
数据验证¶
但如果你在浏览器中访问 http://127.0.0.1:8000/items/foo,你将看到一个友好的 HTTP 错误:
{
"detail": [
{
"type": "int_parsing",
"loc": [
"path",
"item_id"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "foo"
}
]
}
因为路径参数 item_id 的值为 "foo",它不是 int。
如果你提供 float 而不是 int,也会出现同样的错误,例如:http://127.0.0.1:8000/items/4.2
提示
因此,通过同样的 Python 类型声明,FastAPI 为你提供了数据验证功能。
请注意,错误信息也清楚地说明了验证失败的具体位置。
这在开发和调试与 API 交互的代码时非常有帮助。
文档¶
当你打开浏览器访问 http://127.0.0.1:8000/docs 时,你将看到一个自动化的交互式 API 文档,如下所示:

提示
同样,只需相同的 Python 类型声明,FastAPI 就能为你提供自动化的交互式文档(集成了 Swagger UI)。
请注意,该路径参数被声明为整数。
基于标准的优势,替代性文档¶
由于生成的模式基于 OpenAPI 标准,因此有许多兼容工具可用。
正因如此,FastAPI 本身提供了另一种 API 文档(使用 ReDoc),你可以通过 http://127.0.0.1:8000/redoc 访问。

同样,有许多兼容工具。包括针对多种语言的代码生成工具。
Pydantic¶
所有数据验证均由 Pydantic 在后台执行,因此你可以从中获得所有好处。你可以放心使用。
你可以对 str、float、bool 以及许多其他复杂数据类型使用相同的类型声明。
教程的后续章节将探索其中一些类型。
顺序很重要¶
在创建 路径操作 时,可能会遇到固定路径的情况。
例如 /users/me,假设它是为了获取当前用户的数据。
然后你还可以有一个路径 /users/{user_id},用于通过用户 ID 获取特定用户的数据。
因为 路径操作 是按顺序评估的,你需要确保 /users/me 的路径声明在 /users/{user_id} 之前。
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
否则,/users/{user_id} 的路径也会匹配 /users/me,“认为”它接收到了一个值为 "me" 的参数 user_id。
同样,你不能重复定义同一个路径操作。
from fastapi import FastAPI
app = FastAPI()
@app.get("/users")
async def read_users():
return ["Rick", "Morty"]
@app.get("/users")
async def read_users2():
return ["Bean", "Elfo"]
因为路径首先匹配,所以总是会使用第一个定义的路径操作。
预定义值¶
如果你有一个接收 路径参数 的 路径操作,但你希望 路径参数 的有效值是预定义的,你可以使用标准的 Python Enum。
创建一个 Enum 类¶
导入 Enum 并创建一个继承自 str 和 Enum 的子类。
通过继承自 str,API 文档将能够知道这些值必须是 string 类型,并能正确渲染。
然后创建具有固定值的类属性,这些即为可用的有效值。
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
提示
如果你在好奇,“AlexNet”、“ResNet”和“LeNet”只是机器学习 模型 的名称。
声明一个 路径参数¶
然后使用你创建的枚举类 (ModelName) 作为类型注解来创建一个 路径参数。
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
检查文档¶
因为 路径参数 的可用值是预定义的,交互式文档可以很好地展示它们。

使用 Python 枚举¶
路径参数 的值将是一个 枚举成员。
比较 枚举成员¶
你可以将其与你创建的枚举 ModelName 中的 枚举成员 进行比较。
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
获取 枚举值¶
你可以使用 model_name.value,或者更通用的 your_enum_member.value 来获取实际值(在此例中为 str)。
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
提示
你也可以通过 ModelName.lenet.value 访问值 "lenet"。
返回 枚举成员¶
你可以从 路径操作 中返回 枚举成员,即使是嵌套在 JSON 正文中(例如 dict)。
在返回给客户端之前,它们会被转换为相应的值(在此例中为字符串)。
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
在你的客户端中,你将收到如下 JSON 响应:
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
包含路径的路径参数¶
假设你有一个路径为 /files/{file_path} 的 路径操作。
但你需要 file_path 本身包含一个 路径,例如 home/johndoe/myfile.txt。
那么该文件的 URL 将类似于:/files/home/johndoe/myfile.txt。
OpenAPI 支持¶
OpenAPI 不支持声明 路径参数 包含内部 路径 的方式,因为这可能导致难以测试和定义的场景。
尽管如此,你仍然可以在 FastAPI 中实现,使用 Starlette 的内部工具之一。
文档仍然可以正常工作,尽管不会添加任何说明该参数应包含路径的文档。
路径转换器¶
使用 Starlette 的直接选项,你可以通过类似于以下的 URL 声明包含 路径 的 路径参数:
/files/{file_path:path}
在此例中,参数名称为 file_path,最后的部分 :path 告诉它该参数应匹配任何 路径。
因此,你可以这样使用它:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
提示
你可能需要参数包含 /home/johndoe/myfile.txt,并带有前导斜杠 (/)。
在这种情况下,URL 将是:/files//home/johndoe/myfile.txt,在 files 和 home 之间带有双斜杠 (//)。
回顾¶
使用 FastAPI,通过简洁、直观且标准的 Python 类型声明,你可以获得:
- 编辑器支持:错误检查、自动补全等。
- 数据 "解析"
- 数据验证
- API 注解和自动文档
而且你只需要声明一次。
这可能是 FastAPI 相较于其他框架(除了原始性能之外)的主要可见优势。