FastAPI 教程翻译 - 用户指南 3 - 路径参数
FastAPI Tutorial - User Guide - Path Parameters
You can declare path “parameters” or “variables” with the same syntax used by Python format strings:
您可以使用 Python 格式字符串使用的相同语法声明路径『参数』或『变量』:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
The value of the path parameter item_id
will be passed to your function as the argument item_id
.
路径参数 item_id
的值将作为参数 item_id
传递给您的视图函数。
So, if you run this example and go to http://127.0.0.1:8000/items/foo, you will see a response of:
因此,如果运行此示例并转到 http://127.0.0.1:8000/items/foo ,您将看到以下响应:
{"item_id":"foo"}
Path parameters with types
路径参数的类型
You can declare the type of a path parameter in the function, using standard Python type annotations:
您可以使用标准的 Python 类型注释在函数中声明路径参数的类型:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
In this case, item_id
is declared to be an int
.
在这种情况下,item_id
被声明为 int
。
Check
检查
This will give you editor support inside of your function, with error checks, completion, etc.
这将为您提供函数的编辑器支持,包括错误检查,完整性检查等。
Data conversion
数据转换
If you run this example and open your browser at http://127.0.0.1:8000/items/3, you will see a response of:
如果运行此示例并在浏览器中打开 http://127.0.0.1:8000/items/3 ,您将看到以下响应:
{"item_id":3}
Check
检查
Notice that the value your function received (and returned) is
3
, as a Pythonint
, not a string"3"
.请注意,函数收到(并返回)的值是 Python 的
int
值(即3
),而不是字符串『3』
。So, with that type declaration, FastAPI gives you automatic request “parsing”.
因此,有了类型声明,FastAPI 会为您自动提供请求『解析』。
Data validation
数据验证
But if you go to the browser at http://127.0.0.1:8000/items/foo, you will see a nice HTTP error of:
如果您通过浏览器进入 http://127.0.0.1:8000/items/foo ,会看到一个不错的 HTTP 错误页:
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
because the path parameter item_id
had a value of "foo"
, which is not an int
.
因为路径参数 item_id
的值为『foo』
,而不是 int
。
The same error would appear if you provided a float
instead of an int, as in: http://127.0.0.1:8000/items/4.2
如果您提供的是 float
而不是 int
,则会出现相似的错误,例如 http://127.0.0.1:8000/items/4.2
Check
检查
So, with the same Python type declaration, FastAPI gives you data validation.
因此,使用与 Python 类型声明相同的方式,FastAPI 可进行数据验证。
Notice that the error also clearly states exactly the point where the validation didn’t pass.
请注意,错误页清楚地指出了验证未通过的点。
This is incredibly helpful while developing and debugging code that interacts with your API.
在开发和调试与您的 API 交互的代码时,这非常有用。
Documentation
文档
And when you open your browser at http://127.0.0.1:8000/docs, you will see an automatic, interactive, API documentation like:
在浏览器上打开 http://127.0.0.1:8000/docs 时,您将看到一个自动的、交互式的 API 文档,例如:
Check
检查
Again, just with that same Python type declaration, FastAPI gives you automatic, interactive documentation (integrating Swagger UI).
同样,使用与 Python 类型声明相同的方式,FastAPI 为您提供自动的交互式文档(集成 Swagger UI)。
Notice that the path parameter is declared to be an integer.
请注意,路径参数已声明为整数。
Standards-based benefits, alternative documentation
基于标准的好处:备用文档
And because the generated schema is from the OpenAPI standard, there are many compatible tools.
由于生成的架构来自 OpenAPI 标准,因此有许多兼容工具。
Because of this, FastAPI itself provides an alternative API documentation (using ReDoc):
基于这个原因,FastAPI 本身提供了备用的 API 文档(使用 ReDoc):
The same way, there are many compatible tools. Including code generation tools for many languages.
同样,有许多的兼容工具。包括多种语言的代码生成工具。
Pydantic
All the data validation is performed under the hood by Pydantic, so you get all the benefits from it. And you know you are in good hands.
所有的数据验证都是由 Pydantic 实现的,因此您可以从中获得所有好处,而且您知道自己处于良好状态。
You can use the same type declarations with str
, float
, bool
and many other complex data types.
同样的,您可以使用 str
、float
、bool
和许多其他复杂数据类型来进行声明。
Several of these are explored in the next chapters of the tutorial.
本教程的下一章将探讨其中的一些内容。
Order matters
顺序很重要
When creating path operations, you can find situations where you have a fixed path.
在创建路径操作时,您会发现路径固定的情况。
Like /users/me
, let’s say that it’s to get data about the current user.
像 /users/me
一样,假设它是获取有关当前用户的数据。
And then you can also have a path /users/{user_id}
to get data about a specific user by some user ID.
然后,您还可以使用路径 /users/{user_id}
来通过某些用户ID获取有关特定用户的数据。
Because path operations are evaluated in order, you need to make sure that the path for /users/me
is declared before the one for /users/{user_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}
Otherwise, the path for /users/{user_id}
would match also for /users/me
, “thinking” that it’s receiving a parameter user_id
with a value of "me"
.
否则,/users/{user_id}
的路径也将匹配 /users/me
,『认为』它正在接收值为『me』
的参数 user_id
。
Predefined values
预定义值
If you have a path operation that receives a path parameter, but you want the possible valid path parameter values to be predefined, you can use a standard Python Enum
.
如果您的路径操作接收了路径参数,但是想要预定义可能的有效路径参数值,则可以使用标准 Python 的 Enum
。
Create an Enum
class
创建一个 Enum
类
Import Enum
and create a sub-class that inherits from str
and from Enum
.
导入 Enum
并创建一个继承自 str
和 Enum
的子类。
By inheriting from str
the API docs will be able to know that the values must be of type string
and will be able to render correctly.
通过从 str
继承,API 文档将能够知道这些值必须是 string
类型才能正确呈现。
And create class attributes with fixed values, those fixed values will be the available valid values:
并创建具有固定值的类属性,这些固定值将是可用的有效值:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == 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"}
Info
信息
Enumerations (or enums) are available in Python since version 3.4.
Enumerations (or enums) are available in Python 仅在 Python 3.4+ 提供支持。
Tip
提示
If you are wondering, “AlexNet”, “ResNet”, and “LeNet” are just names of Machine Learning models.
如果您想知道『AlexNet』、『ResNet』、『LeNet』,这些只是机器学习模型的名称。
Declare a path parameter
声明路径参数
Then create a path parameter with a type annotation using the enum class you created (ModelName
):
然后使用您创建的 Enum
类(ModelName
)创建带有类型注释的路径参数:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == 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"}
Check the docs
检查文档
Because the available values for the path parameter are specified, the interactive docs can show them nicely:
由于指定了路径参数的可用值,因此交互式文档可以很好地显示它们:
Working with Python enumerations
使用 Python 枚举
The value of the path parameter will be an enumeration member.
路径参数的值将是枚举成员。
Compare enumeration members
比较枚举成员
You can compare it with the enumeration member in your created enum ModelName
:
您可以将其与创建的 enum
类(ModelName
)中的枚举成员进行比较:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == 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"}
Get the enumeration value
获取枚举值
You can get the actual value (a str
in this case) using model_name.value
, or in general, your_enum_member.value
:
您可以使用 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("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == 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"}
Tip
提示
You could also access the value
"lenet"
withModelName.lenet.value
.您也可以通过
ModelName.lenet.value
获得『lenet』
的值。
Return enumeration members
返回枚举成员
You can return enum members from your path operation, even nested in a JSON body (e.g. a dict
).
您可以通过路径操作返回枚举成员,甚至可以嵌套在 JSON 主体(例如 dict
)中。
They will be converted to their corresponding values before returning them to the client:
在将它们返回给客户端之前,它们将被转换为相应的值:
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == 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"}
Path parameters containing paths
包含路径的路径参数
Let’s say you have a path operation with a path /files/{file_path}
.
假设您有一个路径操作,其路径为 /files/{file_path}
。
But you need file_path
itself to contain a path, like home/johndoe/myfile.txt
.
但是您需要 file_path
本身来包含一个路径,例如 home/johndoe/myfile.txt
。
So, the URL for that file would be something like: /files/home/johndoe/myfile.txt
.
那么,该文件的 URL 将类似于:/files/home/johndoe/myfile.txt
。
OpenAPI support
OpenAPI 支持
OpenAPI doesn’t support a way to declare a path parameter to contain a path inside, as that could lead to scenarios that are difficult to test and define.
OpenAPI 不支持声明路径参数包含路径的方法,因为这可能导致难以测试和定义的方案。
Nevertheless, you can still do it in FastAPI, using one of the internal tools from Starlette.
不过,您仍然可以使用 Starlette 的内部工具在 FastAPI 中进行操作。
And the docs would still work, although not adding any documentation telling that the parameter should contain a path.
尽管交互式文档中不会添加任何该参数应包含路径的说明,但这些交互式文档仍然可以使用。
Path convertor
路径转换器
Using an option directly from Starlette you can declare a path parameter containing a path using a URL like:
通过使用直接来自 Starlette 的选项,您可以使用以下 URL 声明包含路径的路径参数:
/files/{file_path:path}
In this case, the name of the parameter is file_path
, and the last part, :path
, tells it that the parameter should match any path.
在这种情况下,参数的名称为 file_path
,最后一部分 :path
告诉它该参数应与任何路径匹配。
So, you can use it with:
因此,您可以将其用于:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_user_me(file_path: str):
return {"file_path": file_path}
Tip
提示
You could need the parameter to contain
/home/johndoe/myfile.txt
, with a leading slash (/
).您可能需要参数为
/home/johndoe/myfile.txt
,并另带有一个斜杠(/
)开头。In that case, the URL would be:
/files//home/johndoe/myfile.txt
, with a double slash (//
) betweenfiles
andhome
.在这种情况下,URL为:
/files//home/johndoe/myfile.txt
,在files
和home
之间使用双斜杠(//
)。
Recap
回顾
With FastAPI, by using short, intuitive and standard Python type declarations, you get:
使用 FastAPI,通过使用简短、直观和标准的 Python 类型声明,您将获得:
-
Editor support: error checks, autocompletion, etc.
编辑器支持:错误检查、自动完成等
-
Data “parsing”
数据『解析』
-
Data validation
数据验证
-
API annotation and automatic documentation
API 批注和自动文档
And you only have to declare them once.
您只需要声明一次即可。
That’s probably the main visible advantage of FastAPI compared to alternative frameworks (apart from the raw performance).
与其他框架相比,这可能是 FastAPI 的主要可见优势(除了原始性能)。