栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python:Fastapi 请求体-嵌套模型

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python:Fastapi 请求体-嵌套模型

请求体 - 字段

字段与使用 Query、Path 和 Body 在路径操作函数中声明额外的校验和元数据的方式相同,可以使用 Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。

注意点:Field 是直接从 pydantic 导入的,而不是像其他的(Query,Path,Body 等)都从 fastapi 导入。

首先导入Field:

from pydantic import Field

其次开始声明模型定义字段:

from pydantic import Field, baseModel


class Items(baseModel):
    name: str
    full_name: Optional[str] = Field(None, min_length=2)
    description: Optional[str] = Field(None, max_length=100)
    price: float = Field(..., gt=0)
    gender: str = Field(..., alias="g")
    tax: int = Field(None, title="用于文档中", description="在文档中显示")

注释信息:

min_length=2 是设置字段的最小长度max_length=100 是设置字段最大长度gt=0 是大于0 [ ge大于等于、lt小于、le小于等于]alias="g" 是取别名title="用于文档中" 显示在生成的docs文档中description="在文档中显示" 显示在生成的docs文档中

然后开始定义接口:

from typing import Optional
from fastapi import FastAPI
from fastapi import Body
from pydantic import Field, baseModel


class Items(baseModel):
    name: str
    full_name: Optional[str] = Field(None, min_length=2)
    description: Optional[str] = Field(None, max_length=100)
    price: float = Field(..., gt=0)
    gender: str = Field(..., alias="g")
    tax: int = Field(None, title="用于文档中", description="在文档中显示")


app = FastAPI()


@app.put("/items/{item_id}")
def read_field(item_id: int, item: Items = Body(..., embed=True)):
    return {"item_id": item_id, "item": item}

然后启动服务:

lifeng@192 fastapiProject % uvicorn field_main:app --reload
INFO:     Will watch for changes in these directories: ['/Users/lifeng/python-projects/python-code/fastapiProject']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [45277] using statreload
INFO:     Started server process [45279]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
WARNING:  StatReload detected file change in 'field_main.py'. Reloading...
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [45279]
INFO:     Started server process [45376]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:55549 - "PUT /items/1 HTTP/1.1" 200 OK

最后请求接口:

PUT :http://127.0.0.1:8000/items/1

传入请求参数:

{
    "item": {
        "name": "haha",
        "price": 2.8,
        "g": "eee"
    }
}

返回响应结果:

{
    "item_id": 1,
    "item": {
        "name": "haha",
        "full_name": null,
        "description": null,
        "price": 2.8,
        "g": "eee",
        "tax": null
    }
}

请求体 - 嵌套模型

就是给属性(字段)定义为拥有子元素的类型,如:name: list 或 name: List),还有就是嵌套子模型(可以直接理解为字段又嵌套一个子字段),如:image: Optional[Image] = None等。

from fastapi import FastAPI
from typing import Optional, List, Set
from pydantic import baseModel, Field


class Image(baseModel):
    url: str
    name: str


class User(baseModel):
    name: str
    full_name: Optional[str] = Field(None)
    age: int = Field(..., ge=0)
    tags: List[str] = []
    email: Set[str] = set()
    image: Image


app = FastAPI()


@app.put("/items/{item_id}")
def read_items(item_id: int, user: User):
    results = {"item_id": item_id, "user": user}
    return results

上述例子User就是声明的模型,Image也是声明的模型,只是Image用在User中,故被称为子模型(嵌套模型),是image属性(字段)拥有的子元素的类型

tags和email是属性含子类型的类型image属于子模型用作类型email属性定义为集合的原因,是可以过滤重复值,保证唯一值,但是在传参时,按列表类型传即可

请求接口:

PUT :http://127.0.0.1:8000/items/1

请求参数:

{
    "name": "haha",
    "age": 11,
    "tags": [
        "1",
        "2"
    ],
    "email": [
        "1",
        "2"
    ],
    "image": {
        "url": "http://example.com/baz.jpg",
        "name": "heihei"
    }
}

请求结果:

{
    "item_id": 1,
    "user": {
        "name": "haha",
        "full_name": null,
        "age": 11,
        "tags": [
            "1",
            "2"
        ],
        "email": [
            "1",
            "2"
        ],
        "image": {
            "url": "http://example.com/baz.jpg",
            "name": "heihei"
        }
    }
}

如果你遇到字段需要定义为url,就像这样的:

from pydantic import baseModel


class Image(baseModel):
    url: str
    name: str

那就直接把url声明为HttpUrl,而不是声明为str:

from pydantic import baseModel, HttpUrl


class Image(baseModel):
    url: HttpUrl
    name: str

因为声明为HttpUrl,该字符串将被检查是否为有效的 URL,若检查出不是有效的URL,则抛出异常:

{
    "detail": [
        {
            "loc": [
                "body",
                "image",
                "url"
            ],
            "msg": "invalid or missing URL scheme",
            "type": "value_error.url.scheme"
        }
    ]
}

有些时候可能会遇到要在子参数中传数组,数组中要传多个参数,那这个时候就需要给子模型定义类型,也称子模型的属性:

from fastapi import FastAPI
from typing import List
from pydantic import baseModel, Field, HttpUrl


class Image(baseModel):
    url: HttpUrl
    name: str


class User(baseModel):
    name: str
    age: int = Field(..., ge=0)
    images: List[Image]


app = FastAPI()


@app.put("/items/{item_id}")
def read_items(item_id: int, user: User):
    results = {"item_id": item_id, "user": user}
    return results

请求接口:

PUT :http://127.0.0.1:8000/items/1

请求参数:

{
    "name": "haha",
    "age": 11,
    "images": [
        {
            "url": "http://example.com/baz.jpg",
            "name": "heihei"
        },
        {
            "url": "http://example.com/baz.jpg",
            "name": "heihei"
        },
        {
            "url": "http://example.com/baz.jpg",
            "name": "heihei"
        }
    ]
}

请求结果:

{
    "item_id": 1,
    "user": {
        "name": "haha",
        "age": 11,
        "images": [
            {
                "url": "http://example.com/baz.jpg",
                "name": "heihei"
            },
            {
                "url": "http://example.com/baz.jpg",
                "name": "heihei"
            },
            {
                "url": "http://example.com/baz.jpg",
                "name": "heihei"
            }
        ]
    }
}

你还可以自定义任意深度的嵌套模型:

from fastapi import FastAPI
from typing import List, Optional, Set
from pydantic import baseModel, HttpUrl

app = FastAPI()


class Image(baseModel):
    url: HttpUrl
    name: str


class Item(baseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None
    tags: Set[str] = set()
    images: List[Image]


class Offer(baseModel):
    name: str
    description: Optional[str] = None
    price: float
    items: List[Item]


@app.post("/items/")
async def read_items(offer: Offer):
    return offer

请求接口:

POST :http://127.0.0.1:8000/items

请求参数:

{
    "name": "haha",
    "price": 3.9,
    "items": [
        {
            "name": "heihei",
            "price": 4.99,
            "tags": [
                1,
                2,
                3,
                3,
                3,
                3
            ],
            "images": [
                {
                    "url": "http://example.com/baz.jpg",
                    "name": "heihei"
                }
            ]
        }
    ]
}

请求结果:

{
    "name": "haha",
    "description": null,
    "price": 3.9,
    "items": [
        {
            "name": "heihei",
            "description": null,
            "price": 4.99,
            "tax": null,
            "tags": [
                "1",
                "3",
                "2"
            ],
            "images": [
                {
                    "url": "http://example.com/baz.jpg",
                    "name": "heihei"
                }
            ]
        }
    ]
}

从请求结果可以看到,请求参数中的tags是一个数组,其实在接口中是一个集合,集合有去重功能,所以返回的结果自然就只有一个3了。


今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!

未完成,待续……

一直在努力,希望你也是!

微信搜索公众号:就用python

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/739642.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号