首页>文档>FastAPI>fastapi中文手册:Body – Nested Models(嵌套模型)

fastapi中文手册:Body – Nested Models(嵌套模型)

fastapi中文手册:Body - Nested Models(嵌套模型)

FastAPI 是一个高性能 Web 框架,用于构建 API。

主要特性:

  • 快速:非常高的性能,与 NodeJS 和 Go 相当
  • 快速编码:将功能开发速度提高约 200% 至 300%
  • 更少的错误:减少约 40% 的人为错误
  • 直观:强大的编辑器支持,自动补全无处不在,调试时间更少
  • 简易:旨在易于使用和学习,减少阅读文档的时间。
  • 简短:减少代码重复。
  • 稳健:获取可用于生产环境的代码,具有自动交互式文档
  • 基于标准:基于并完全兼容 API 的开放标准 OpenAPI 和 JSON Schema 

使用FastAPI,您可以定义,验证,生成文档和使用任意深度嵌套的模型(这要归功于Pydantic)。

一、List 字段

您可以将属性定义为子类型。 例如,Python的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 = [] 

上面的设定tagslist项目类型,尽管它并没有声明每个项目的类型。

二、具有子类型的List字段

但是Python有一种特定的方法来声明带有子类型的列表:

1. 导入typingList

首先,导入Python中typing类的List

from typing import List 

2. 声明List的子类

声明类型有子类,比如listdicttuple

  • typing 导入
  • 将子类型用花括号包起来: []

from typing import List

my_list: List[str]

这就是类型声明的所有标准Python语法。

对具有子类型的模型属性使用相同的标准语法。

因此,在我们的例子中,我们可以设置tags具体为字符串的列表

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

三、设置类型

但是当我们思考一下,如果tags里的字符串必须唯一,不能重复。

并且Python有专门的数据类型对于这种唯一的项目,就是set

我们可以导入 Set 并且声明 tagsset 的类,子类是 str:

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

这样,即使您收到带有重复数据的请求,该请求也会被转换为一组唯一的项目。

而且,每当您输出该数据时,即使源重复,它们也将作为一组唯一项输出。

并且它也会被相应地注释/生成文档。

四、嵌套的模型

每个Pydantic模型的每一个属性都有一个类型。

而且,这个类型可以自身是另一个Pydantic模型。

因此,您可以使用特定的属性名称,类型和验证来声明深度嵌套的JSON对象。并且,可以任意嵌套。

1. 定义一个子模型

例如,我们可以定义Image类型:

from typing import Set

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Image(BaseModel):
    url: str name: str 
2. 使用子模型作为类型

然后我们可以将其用作属性的类型:

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

这意味着FastAPI将期望类似于以下内容的请求体:

{
    "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"
    }
}

同样地,在FastAPI声明,您将获得:

  • 编辑器支持(补全),即使是嵌套模型
  • 数据转换
  • 数据验证
  • 自动文档

五、特殊类型和验证

除了正常的单数类型,如strintfloat等外,您还可以使用从str继承的更复杂的单数类型。

要查看所有选项,请查看Pydantic’s exotic types。 您将在下一章中看到一些示例。

例如,在Image模型中,我们需要一个url字段,我们可以将它声明为Pydantic中的UrlStr,而不是简单的str

from typing import Set

from fastapi import FastAPI
from pydantic import BaseModel, UrlStr 
app = FastAPI()

class Image(BaseModel):
    url: UrlStr
    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

该字符串将被检查为有效的URL,并在 JSON Schema / OpenAPI中进行记录。

六、带有子模型列表的属性

您还可以将Pydantic模型用作listset等的子类型:

from typing import List, Set

from fastapi import FastAPI
from pydantic import BaseModel, UrlStr

app = FastAPI()

class Image(BaseModel):
    url: UrlStr
    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

这将期望(转换,验证,记录等)JSON请求体,例如:

{
    "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"
        }
    ]
}

七、深层嵌套模型

您可以定义任意深度嵌套的模型:

from typing import List, Set

from fastapi import FastAPI
from pydantic import BaseModel, UrlStr

app = FastAPI()

class Image(BaseModel):
    url: UrlStr
    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

八、全部列表的请求体

如果期望的JSON主体的顶级值为JSON数组(Python列表),则可以在函数的参数中声明类型,与Pydantic模型相同:

images: List[Image]

如下:

from typing import List

from fastapi import FastAPI
from pydantic import BaseModel, UrlStr

app = FastAPI()

class Image(BaseModel):
    url: UrlStr
    name: str

@app.post("/images/multiple/")
async def create_multiple_images(*, images: List[Image]):
    return images

九、编辑器支持

无论在哪里你都可以得到编辑器支持。

即使在列表里的项:

fastapi中文手册:Body - Nested Models(嵌套模型)

如果您直接使用dict而不是Pydantic模型,那么您将无法获得这种编辑器支持。

但是您也不必担心它们,传入的dict会自动转换,您的输出也会自动转换为JSON

十、任意 dict的主体

您还可以使用某些类型的键和其他类型的值将主体声明为dict

无需事先知道有效的字段/属性名称是什么(就像Pydantic模型一样)。

如果你不知道你将要接受到什么样的key,用dict很有用。

其他有用的情况是当您想使用其他类型的键时,例如 int

下面来看看这个例子:

在这种情况下,您可以接受任何dict,只要它具有带有float值的int键即可:

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

记住:JSON只支持str作为键。但是Pydantic会自动转换数据

这意味着,即使您的API客户端只能将字符串作为键发送,只要这些字符串包含纯整数,Pydantic就会对其进行转换并验证它们。

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索