Body - Nested Models


Body - Nested Models

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


@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

tags 表示实体列表,尽管没有显式声明每个实体的类型

List fields with subtype

可以通过 python 的 typing 标准库来声明具有子类型的列表,例如

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

使用 set 类型可以声明一组不重复的实体

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

通过 set,即使接收到一组重复数据,也将会被自动转化为一组没有重复的实体

这些也会被自动加入注解

Nested Models

Pydantic 模型的每一个属性都有其类型,并且这些类型可以是另一个 Pydantic 模型,因此可以声明嵌套的 JSON 对象,并且这些对象可以有特定的属性名称,类型和验证

所有这些都可以被任意嵌套

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

在上面的例子中,Image 模型作为 Item 模型的一个属性

FastAPI 期望的 request body 类似于

{
    "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,将可以获得

  • IDE 支持
  • 数据自动转换
  • 数据验证
  • 自动文档

Special types and validation

除了类似于 strintfloat 普通的单一类型,还可以使用继承于 str 的更加复杂的类型

例如,在 Image 模型里面,我们可以用 HttpUrl 类型来代替普通的 str,例如

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

url 属性将会自动检查是否是合法的 URL,并且在自动文档中标注

Attributes with lists of submodels

Ptdantic 模型同样可以作为 listset 等的子类型,例如

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

上面的例子将会期待 body

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

Deeply nested models

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

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

Bodies of pure lists

如果希望 JSON body 的顶层值是一个 JSON array,可以如下声明

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

Bodies of arbitrary dicts

同样可以使用具有某些类型的键和某些类型的值的 dict 来声明 request body

可以被用在如果某些键和值名字不确定的情况,例如

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

在上述例子中,只要是整形的 key 和浮点型的 value 就会被接受

注:JSON 只支持 str 作为键,但是 Pydantic 模型可以对数据进行自动转换。即,即使客户端只支持发送字符串作为键,只要这些键只包含纯整数,Pydantic 就会进行自动转化和验证


文章作者: qiufeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 qiufeng !
评论
 上一篇
Schema Extra - Example Schema Extra - Example
Schema Extra - Example Schema Extra - Example可以为 JSON 模式定义额外的信息 一个常见的用法是为 api 文档添加一个例子 有如下的几种方式来定义额外的 JSON 模式信息 P
2020-04-14
下一篇 
Body - Multiple Parameters Body - Multiple Parameters
Mix Path, Query and body parameters我们可以自由的混合 Path 和 Query 和 request body,FastAPI 知道如何自动处理 request body 参数也是可选的 from fast
2020-04-13
  目录