路径参数¶
您可以使用与 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 与其他框架相比最主要的显而易见的好处(除了原始性能)。