首先,你必须导入它:
-```Python hl_lines="2"
-{!../../../docs_src/body_fields/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="2"
+ {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
!!! warning
注意,`Field` 是直接从 `pydantic` 导入的,而不是像其他的(`Query`,`Path`,`Body` 等)都从 `fastapi` 导入。
然后,你可以对模型属性使用 `Field`:
-```Python hl_lines="9-10"
-{!../../../docs_src/body_fields/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12-15"
+ {!> ../../../docs_src/body_fields/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="9-12"
+ {!> ../../../docs_src/body_fields/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="11-14"
+ {!> ../../../docs_src/body_fields/tutorial001.py!}
+ ```
`Field` 的工作方式和 `Query`、`Path` 和 `Body` 相同,包括它们的参数等等也完全相同。
你还可以通过将默认值设置为 `None` 来将请求体参数声明为可选参数:
-```Python hl_lines="17-19"
-{!../../../docs_src/body_multiple_params/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="18-20"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-20"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="17-19"
+ {!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="19-21"
+ {!> ../../../docs_src/body_multiple_params/tutorial001.py!}
+ ```
!!! note
请注意,在这种情况下,将从请求体获取的 `item` 是可选的。因为它的默认值为 `None`。
但是你也可以声明多个请求体参数,例如 `item` 和 `user`:
-```Python hl_lines="20"
-{!../../../docs_src/body_multiple_params/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial002.py!}
+ ```
在这种情况下,**FastAPI** 将注意到该函数中有多个请求体参数(两个 Pydantic 模型参数)。
但是你可以使用 `Body` 指示 **FastAPI** 将其作为请求体的另一个键进行处理。
-```Python hl_lines="22"
-{!../../../docs_src/body_multiple_params/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="23"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/body_multiple_params/tutorial003.py!}
+ ```
在这种情况下,**FastAPI** 将期望像这样的请求体:
比如:
-```Python hl_lines="25"
-{!../../../docs_src/body_multiple_params/tutorial004.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="28"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="25"
+ {!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="27"
+ {!> ../../../docs_src/body_multiple_params/tutorial004.py!}
+ ```
!!! info
`Body` 同样具有与 `Query`、`Path` 以及其他后面将看到的类完全相同的额外校验和元数据参数。
比如:
-```Python hl_lines="15"
-{!../../../docs_src/body_multiple_params/tutorial005.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="17"
+ {!> ../../../docs_src/body_multiple_params/tutorial005.py!}
+ ```
在这种情况下,**FastAPI** 将期望像这样的请求体:
你可以将一个属性定义为拥有子元素的类型。例如 Python `list`:
-```Python hl_lines="12"
-{!../../../docs_src/body_nested_models/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial001.py!}
+ ```
这将使 `tags` 成为一个由元素组成的列表。不过它没有声明每个元素的类型。
首先,从 Python 的标准库 `typing` 模块中导入 `List`:
```Python hl_lines="1"
-{!../../../docs_src/body_nested_models/tutorial002.py!}
+{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
### 声明具有子类型的 List
因此,在我们的示例中,我们可以将 `tags` 明确地指定为一个「字符串列表」:
-```Python hl_lines="14"
-{!../../../docs_src/body_nested_models/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial002.py!}
+ ```
## Set 类型
然后我们可以导入 `Set` 并将 `tag` 声明为一个由 `str` 组成的 `set`:
-```Python hl_lines="1 14"
-{!../../../docs_src/body_nested_models/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="14"
+ {!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 14"
+ {!> ../../../docs_src/body_nested_models/tutorial003.py!}
+ ```
这样,即使你收到带有重复数据的请求,这些数据也会被转换为一组唯一项。
例如,我们可以定义一个 `Image` 模型:
-```Python hl_lines="9 10 11"
-{!../../../docs_src/body_nested_models/tutorial004.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7-9"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9-11"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```
### 将子模型用作类型
然后我们可以将其用作一个属性的类型:
-```Python hl_lines="20"
-{!../../../docs_src/body_nested_models/tutorial004.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial004.py!}
+ ```
这意味着 **FastAPI** 将期望类似于以下内容的请求体:
例如,在 `Image` 模型中我们有一个 `url` 字段,我们可以把它声明为 Pydantic 的 `HttpUrl`,而不是 `str`:
-```Python hl_lines="4 10"
-{!../../../docs_src/body_nested_models/tutorial005.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="2 8"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 10"
+ {!> ../../../docs_src/body_nested_models/tutorial005.py!}
+ ```
该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
你还可以将 Pydantic 模型用作 `list`、`set` 等的子类型:
-```Python hl_lines="20"
-{!../../../docs_src/body_nested_models/tutorial006.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="20"
+ {!> ../../../docs_src/body_nested_models/tutorial006.py!}
+ ```
这将期望(转换,校验,记录文档等)下面这样的 JSON 请求体:
你可以定义任意深度的嵌套模型:
-```Python hl_lines="9 14 20 23 27"
-{!../../../docs_src/body_nested_models/tutorial007.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 12 18 21 25"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 14 20 23 27"
+ {!> ../../../docs_src/body_nested_models/tutorial007.py!}
+ ```
!!! info
请注意 `Offer` 拥有一组 `Item` 而反过来 `Item` 又是一个可选的 `Image` 列表是如何发生的。
例如:
-```Python hl_lines="15"
-{!../../../docs_src/body_nested_models/tutorial008.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="13"
+ {!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="15"
+ {!> ../../../docs_src/body_nested_models/tutorial008.py!}
+ ```
## 无处不在的编辑器支持
在下面的例子中,你将接受任意键为 `int` 类型并且值为 `float` 类型的 `dict`:
-```Python hl_lines="15"
-{!../../../docs_src/body_nested_models/tutorial009.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/body_nested_models/tutorial009.py!}
+ ```
!!! tip
请记住 JSON 仅支持将 `str` 作为键。
首先,你需要从 `pydantic` 中导入 `BaseModel`:
-```Python hl_lines="2"
-{!../../../docs_src/body/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="2"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
## 创建数据模型
使用标准的 Python 类型来声明所有属性:
-```Python hl_lines="5-9"
-{!../../../docs_src/body/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="5-9"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="7-11"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
和声明查询参数时一样,当一个模型属性具有默认值时,它不是必需的。否则它是一个必需属性。将默认值设为 `None` 可使其成为可选属性。
使用与声明路径和查询参数的相同方式声明请求体,即可将其添加到「路径操作」中:
-```Python hl_lines="16"
-{!../../../docs_src/body/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/body/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial001.py!}
+ ```
...并且将它的类型声明为你创建的 `Item` 模型。
在函数内部,你可以直接访问模型对象的所有属性:
-```Python hl_lines="19"
-{!../../../docs_src/body/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="19"
+ {!> ../../../docs_src/body/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="21"
+ {!> ../../../docs_src/body/tutorial002.py!}
+ ```
## 请求体 + 路径参数
**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
-```Python hl_lines="15-16"
-{!../../../docs_src/body/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="15-16"
+ {!> ../../../docs_src/body/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/body/tutorial003.py!}
+ ```
## 请求体 + 路径参数 + 查询参数
**FastAPI** 会识别它们中的每一个,并从正确的位置获取数据。
-```Python hl_lines="16"
-{!../../../docs_src/body/tutorial004.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="16"
+ {!> ../../../docs_src/body/tutorial004_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/body/tutorial004.py!}
+ ```
函数参数将依次按如下规则进行识别:
首先,导入 `Cookie`:
-```Python hl_lines="3"
-{!../../../docs_src/cookie_params/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
## 声明 `Cookie` 参数
第一个值是参数的默认值,同时也可以传递所有验证参数或注释参数,来校验参数:
-```Python hl_lines="9"
-{!../../../docs_src/cookie_params/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/cookie_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/cookie_params/tutorial001.py!}
+ ```
!!! note "技术细节"
`Cookie` 、`Path` 、`Query`是兄弟类,它们都继承自公共的 `Param` 类
下面是一个*路径操作*的示例,其中的参数使用了上面的一些类型。
-```Python hl_lines="1 3 12-16"
-{!../../../docs_src/extra_data_types/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="1 3 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 3 13-17"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="1 2 11-15"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="1 2 12-16"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
注意,函数内的参数有原生的数据类型,你可以,例如,执行正常的日期操作,如:
-```Python hl_lines="18-19"
-{!../../../docs_src/extra_data_types/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="19-20"
+ {!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="17-18"
+ {!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="18-19"
+ {!> ../../../docs_src/extra_data_types/tutorial001.py!}
+ ```
下面是应该如何根据它们的密码字段以及使用位置去定义模型的大概思路:
-```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
-{!../../../docs_src/extra_models/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
+ {!> ../../../docs_src/extra_models/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
+ {!> ../../../docs_src/extra_models/tutorial001.py!}
+ ```
### 关于 `**user_in.dict()`
这样,我们可以仅声明模型之间的差异部分(具有明文的 `password`、具有 `hashed_password` 以及不包括密码)。
-```Python hl_lines="9 15-16 19-20 23-24"
-{!../../../docs_src/extra_models/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7 13-14 17-18 21-22"
+ {!> ../../../docs_src/extra_models/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 15-16 19-20 23-24"
+ {!> ../../../docs_src/extra_models/tutorial002.py!}
+ ```
## `Union` 或者 `anyOf`
!!! note
定义一个 <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a> 类型时,首先包括最详细的类型,然后是不太详细的类型。在下面的示例中,更详细的 `PlaneItem` 位于 `Union[PlaneItem,CarItem]` 中的 `CarItem` 之前。
-```Python hl_lines="1 14-15 18-20 33"
-{!../../../docs_src/extra_models/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 14-15 18-20 33"
+ {!> ../../../docs_src/extra_models/tutorial003.py!}
+ ```
## 模型列表
为此,请使用标准的 Python `typing.List`:
-```Python hl_lines="1 20"
-{!../../../docs_src/extra_models/tutorial004.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="18"
+ {!> ../../../docs_src/extra_models/tutorial004_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 20"
+ {!> ../../../docs_src/extra_models/tutorial004.py!}
+ ```
## 任意 `dict` 构成的响应
在这种情况下,你可以使用 `typing.Dict`:
-```Python hl_lines="1 8"
-{!../../../docs_src/extra_models/tutorial005.py!}
-```
+=== "Python 3.9+"
+
+ ```Python hl_lines="6"
+ {!> ../../../docs_src/extra_models/tutorial005_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="1 8"
+ {!> ../../../docs_src/extra_models/tutorial005.py!}
+ ```
## 总结
首先导入 `Header`:
-```Python hl_lines="3"
-{!../../../docs_src/header_params/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
## 声明 `Header` 参数
第一个值是默认值,你可以传递所有的额外验证或注释参数:
-```Python hl_lines="9"
-{!../../../docs_src/header_params/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial001.py!}
+ ```
!!! note "技术细节"
`Header` 是 `Path`, `Query` 和 `Cookie` 的兄弟类型。它也继承自通用的 `Param` 类.
如果出于某些原因,你需要禁用下划线到连字符的自动转换,设置`Header`的参数 `convert_underscores` 为 `False`:
-```Python hl_lines="10"
-{!../../../docs_src/header_params/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="12"
+ {!> ../../../docs_src/header_params/tutorial002_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/header_params/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial002.py!}
+ ```
!!! warning
在设置 `convert_underscores` 为 `False` 之前,请记住,一些HTTP代理和服务器不允许使用带有下划线的headers。
比如, 为了声明一个 `X-Token` header 可以出现多次,你可以这样写:
-```Python hl_lines="9"
-{!../../../docs_src/header_params/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/header_params/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ Prefer to use the `Annotated` version if possible.
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/header_params/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.9+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003_py39.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/header_params/tutorial003.py!}
+ ```
如果你与*路径操作*通信时发送两个HTTP headers,就像:
首先,从 `fastapi` 导入 `Path`:
-```Python hl_lines="1"
-{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="1 3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="3-4"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="1"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="3"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
## 声明元数据
例如,要声明路径参数 `item_id`的 `title` 元数据值,你可以输入:
-```Python hl_lines="8"
-{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="11"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="8"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="10"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
+ ```
!!! note
路径参数总是必需的,因为它必须是路径的一部分。
因此,你可以将函数声明为:
-```Python hl_lines="7"
-{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
-```
+=== "Python 3.6 non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
+ ```
## 按需对参数排序的技巧
让我们以下面的应用程序为例:
-```Python hl_lines="7"
-{!../../../docs_src/query_params_str_validations/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="7"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9"
+ {!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
+ ```
查询参数 `q` 的类型为 `str`,默认值为 `None`,因此它是可选的。
* `@app.delete()`
* 等等。
-```Python hl_lines="17"
-{!../../../docs_src/response_model/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="17 22 24-27"
+ {!> ../../../docs_src/response_model/tutorial001.py!}
+ ```
!!! note
注意,`response_model`是「装饰器」方法(`get`,`post` 等)的一个参数。不像之前的所有参数和请求体,它不属于*路径操作函数*。
相反,我们可以创建一个有明文密码的输入模型和一个没有明文密码的输出模型:
-```Python hl_lines="9 11 16"
-{!../../../docs_src/response_model/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="9 11 16"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
这样,即便我们的*路径操作函数*将会返回包含密码的相同输入用户:
-```Python hl_lines="24"
-{!../../../docs_src/response_model/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="24"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
...我们已经将 `response_model` 声明为了不包含密码的 `UserOut` 模型:
-```Python hl_lines="22"
-{!../../../docs_src/response_model/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="22"
+ {!> ../../../docs_src/response_model/tutorial003.py!}
+ ```
因此,**FastAPI** 将会负责过滤掉未在输出模型中声明的所有数据(使用 Pydantic)。
您可以使用 `Config` 和 `schema_extra` 为Pydantic模型声明一个示例,如<a href="https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic 文档:定制 Schema </a>中所述:
-```Python hl_lines="15-23"
-{!../../../docs_src/schema_extra_example/tutorial001.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="13-21"
+ {!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="15-23"
+ {!> ../../../docs_src/schema_extra_example/tutorial001.py!}
+ ```
这些额外的信息将按原样添加到输出的JSON模式中。
在 `Field`, `Path`, `Query`, `Body` 和其他你之后将会看到的工厂函数,你可以为JSON 模式声明额外信息,你也可以通过给工厂函数传递其他的任意参数来给JSON 模式声明额外信息,比如增加 `example`:
-```Python hl_lines="4 10-13"
-{!../../../docs_src/schema_extra_example/tutorial002.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="2 8-11"
+ {!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="4 10-13"
+ {!> ../../../docs_src/schema_extra_example/tutorial002.py!}
+ ```
!!! warning
请记住,传递的那些额外参数不会添加任何验证,只会添加注释,用于文档的目的。
比如,你可以将请求体的一个 `example` 传递给 `Body`:
-```Python hl_lines="20-25"
-{!../../../docs_src/schema_extra_example/tutorial003.py!}
-```
+=== "Python 3.10+"
+
+ ```Python hl_lines="22-27"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
+ ```
+
+=== "Python 3.9+"
+
+ ```Python hl_lines="22-27"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python hl_lines="23-28"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
+ ```
+
+=== "Python 3.10+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="18-23"
+ {!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python hl_lines="20-25"
+ {!> ../../../docs_src/schema_extra_example/tutorial003.py!}
+ ```
## 文档 UI 中的例子
把下面的示例代码复制到 `main.py`:
-```Python
-{!../../../docs_src/security/tutorial001.py!}
-```
+=== "Python 3.9+"
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001_an_py39.py!}
+ ```
+
+=== "Python 3.6+"
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001_an.py!}
+ ```
+
+=== "Python 3.6+ non-Annotated"
+
+ !!! tip
+ 尽可能选择使用 `Annotated` 的版本。
+
+ ```Python
+ {!> ../../../docs_src/security/tutorial001.py!}
+ ```
## 运行