FastAPI 教程翻译 - 用户指南 10 - 请求主体 - 嵌套模型
FastAPI Tutorial - User Guide - Body - Nested Models
With FastAPI, you can define, validate, document, and use arbitrarily deeply nested models (thanks to Pydantic).
使用 FastAPI,您可以定义、验证、文档和使用任意深度嵌套的模型(感谢 Pydantic)。
List fields
列表字段
You can define an attribute to be a subtype. For example, a Python
您可以将属性定义为子类型。例如,Python 的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: list = [] @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
This will make
这将使
List fields with subtype
具有子类型的列表字段
But Python has a specific way to declare lists with subtypes:
Python 有一种特定的方法来声明带有子类型的列表:
Import typing’s List
导入 typing 的 List
First, import
首先,从标准 Python 的 typing 模块中导入 List:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from typing import List from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: List[str] = [] @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
Declare a List with a subtype
声明带有子类型的 List
To declare types that have subtypes, like
声明具有子类型的类型,例如
-
Import them from the
typing module从
typing 模块导入 -
Pass the subtype(s) as “type arguments” using square brackets:
[ and] 使用方括号将子类型作为『类型实参』:
[ 和]
1 2 3 | from typing import List my_list: List[str] |
That’s all standard Python syntax for type declarations.
这就是类型声明的所有标准 Python 语法。
Use that same standard syntax for model attributes with subtypes.
对具有子类型的模型属性使用相同的标准语法。
So, in our example, we can make
因此,在我们的示例中,我们可以将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from typing import List from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: List[str] = [] @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
Set types
设置类型
But then we think about it, and realize that tags shouldn’t repeat, they would probably be unique strings.
但是随后我们考虑了一下,意识到标签不应该重复,它们可能是唯一的字符串。
And Python has a special data type for sets of unique items, the
而且 Python 具有一组特殊的数据类型来存储唯一项,即
Then we can import
然后我们可以导入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from typing import Set from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = set() @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
这样,即使您收到带有重复数据的请求,该请求也将被转换为一组唯一的项目。
And whenever you output that data, even if the source had duplicates, it will be output as a set of unique items.
而且,每当您输出该数据时,即使源重复,它们也将作为一组唯一项输出。
And it will be annotated / documented accordingly too.
而且它也会获得相应的注释 / 文档。
Nested Models
嵌套模型
Each attribute of a Pydantic model has a type.
Pydantic 模型的每个属性都有一个类型。
But that type can itself be another Pydantic model.
但是该类型本身可以是另一种 Pydantic 模型。
So, you can declare deeply nested JSON
因此,您可以使用特定的属性名称、类型和验证来声明深度嵌套的 JSON 对象。
All that, arbitrarily nested.
所有这些,任意嵌套。
Define a submodel
定义子模型
For example, we can define an
例如,我们可以定义一个 Image 模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from typing import Set from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Image(BaseModel): url: str name: str class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = [] image: Image = None @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
Use the submodel as a type
使用子模型作为类型
And then we can use it as the type of an attribute:
然后我们可以将其用作属性的类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from typing import Set from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Image(BaseModel): url: str name: str class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = [] image: Image = None @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
This would mean that FastAPI would expect a body similar to:
这意味着 FastAPI 将期望类似于以下内容的请求主体:
1 2 3 4 5 6 7 8 9 10 11 | { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2, "tags": ["rock", "metal", "bar"], "image": { "url": "http://example.com/baz.jpg", "name": "The Foo live" } } |
Again, doing just that declaration, with FastAPI you get:
同样,仅使用 FastAPI 进行声明,您将获得:
-
Editor support (completion, etc), even for nested models
编辑器支持(完成等),甚至对于嵌套模型
-
Data conversion
数据转换
-
Data validation
数据验证
-
Automatic documentation
自动文档
Special types and validation
特殊类型和验证
Apart from normal singular types like
除了正常的单类型(如
To see all the options you have, checkout the docs for Pydantic’s exotic types. You will see some examples in the next chapter.
要查看所有选项,请查看文档 Pydantic的奇异类型。您将在下一章中看到一些示例。
For example, as in the
例如,在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from typing import Set from fastapi import FastAPI from pydantic import BaseModel, HttpUrl app = FastAPI() class Image(BaseModel): url: HttpUrl name: str class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = [] image: Image = None @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
该字符串将被检查为有效的 URL,并获得 JSON 模式 / OpenAPI 的文档。
Attributes with lists of submodels
具有子模型列表的属性
You can also use Pydantic models as subtypes of
您还可以将 Pydantic 模型用作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from typing import List, Set from fastapi import FastAPI from pydantic import BaseModel, HttpUrl app = FastAPI() class Image(BaseModel): url: HttpUrl name: str class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = [] images: List[Image] = None @app.put("/items/{item_id}") async def update_item(*, item_id: int, item: Item): results = {"item_id": item_id, "item": item} return results |
This will expect (convert, validate, document, etc) a JSON body like:
这将期望获得(转换、验证、文档等)JSON 主体,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | { "name": "Foo", "description": "The pretender", "price": 42.0, "tax": 3.2, "tags": [ "rock", "metal", "bar" ], "images": [ { "url": "http://example.com/baz.jpg", "name": "The Foo live" }, { "url": "http://example.com/dave.jpg", "name": "The Baz" } ] } |
Info
信息
Notice how the
images key now has a list of image objects.请注意,
images 键现在如何具有图像对象列表。
Deeply nested models
深度嵌套模型
You can define arbitrarily deeply nested models:
您可以定义任意深度嵌套的模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | from typing import List, Set from fastapi import FastAPI from pydantic import BaseModel, HttpUrl app = FastAPI() class Image(BaseModel): url: HttpUrl name: str class Item(BaseModel): name: str description: str = None price: float tax: float = None tags: Set[str] = [] images: List[Image] = None class Offer(BaseModel): name: str description: str = None price: float items: List[Item] @app.post("/offers/") async def create_offer(*, offer: Offer): return offer |
Info
信息
Notice how
Offer as a list ofItem s, which in turn have an optional list ofImage s请注意,如何使
offer 包含Item 的列表,而Item 又包含Image 的可选列表。
Bodies of pure lists
纯列表请求主体
If the top level value of the JSON body you expect is a JSON
如果您期望的 JSON 主体的顶层值为 JSON 的
1 | images: List[Image] |
as in:
如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from typing import List from fastapi import FastAPI from pydantic import BaseModel, HttpUrl app = FastAPI() class Image(BaseModel): url: HttpUrl name: str @app.post("/images/multiple/") async def create_multiple_images(*, images: List[Image]): return images |
Editor support everywhere
编辑器无处不在
And you get editor support everywhere.
而且您到处都能获得编辑器支持。
Even for items inside of lists:
甚至是列表中的元素:

You couldn’t get this kind of editor support if you where working directly with
如果您直接使用
But you don’t have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too.
但是您也不必担心它们,传入的
Bodies of arbitrary dict s
任意 dict 的请求主体
You can also declare a body as a
您还可以使用某些类型的键和值将请求主体声明为
Without having to know beforehand what are the valid field/attribute names (as would be the case with Pydantic models).
无需事先知道有效的字段 / 属性名是什么(就像 Pydantic 模型那样)。
This would be useful if you want to receive keys that you don’t already know.
如果您想接收未知的密钥,这将很有用。
Other useful case is when you want to have keys of other type, e.g.
其他有用的情况是当您想使用其他类型的键时,例如
That’s what we are going to see here.
这就是我们在这里看到的。
In this case, you would accept any
在这种情况下,您将接受任何具有值为
1 2 3 4 5 6 7 8 9 10 | from typing import Dict from fastapi import FastAPI app = FastAPI() @app.post("/index-weights/") async def create_index_weights(weights: Dict[int, float]): return weights |
Tip
提示
Have in mind that JSON only supports
str as keys.请记住,JSON 仅支持将
str 作为键。But Pydantic has automatic data conversion.
但是 Pydantic 具有自动数据转换功能。
This means that, even though your API clients can only send strings as keys, as long as those strings contain pure integers, Pydantic will convert them and validate them.
这意味着,即使您的 API 客户端只能将字符串作为键发送,只要这些字符串包含纯整数,Pydantic 就会对其进行转换并验证它们。
And the
dict you receive asweights will actually haveint keys andfloat values.而您的
weights 收到的dict 实际上将具有int 键和float 值。
Recap
回顾
With FastAPI you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant.
使用 FastAPI,您将拥有 Pydantic 模型提供的最大灵活性,同时使您的代码简短和美观。
But with all the benefits:
并且有下列所有的好处:
-
Editor support (completion everywhere!)
编辑器支持(无处不在!)
-
Data conversion (a.k.a. parsing / serialization)
数据转换(也称为解析 / 序列化)
-
Data validation
数据验证
-
Schema documentation
模式文档
-
Automatic docs
自动文档