04 FastApi的请求体

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了04 FastApi的请求体相关的知识,希望对你有一定的参考价值。

参考技术A

客户端发给服务端的数据,一般通过 Pydantic 模型声明请求体
不可通过 GET 操作发送请求体,可通过 POST , DELETE , PUT , PATCH

当模型属性有默认值时,它不是必须的, 否则为必须属性
下图中 name , age , 为必需属性, address phone 为非必须属性

在函数中参数传递中使用类型提示即可

Fastapi 非常智能,自动将请求体数据转化为json格式读取,且会根据类型提示校验数据类型

FastAPI Web框架 [1.5]

学习,记录一下,方便回顾。

请求体 - 字段

#   与使用 Query、Path 和 Body 在路径操作函数中声明额外的校验和元数据的方式相同,你可以使用 Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。
from fastapi import FastAPI,Body
from typing import Optional
from pydantic import BaseModel,Field    #注意,Field 是直接从 pydantic 导入的,而不是像其他的(Query,Path,Body 等)都从 fastapi 导入。

app = FastAPI()

class Item(BaseModel):          #  声明模型属性
    name:str
    description:Optional[str] = Field(
        None, title="The description of the item",  max_length=300
    )
    price:float = Field(...,gt=0,description="The price must be greater than zero")
    tax:Optional[float] = None

@app.put("/items/item_id")
async def update_item(
        item_id:int,
        item:Item = Body(...,embed=True)
):
    results = 
        "item_id":item_id,
        "item":Item
    
    return results
# Field 的工作方式和 Query、Path 和 Body 相同,包括它们的参数等等也完全相同
#   实际上,Query、Path 和其他你将在之后看到的类,创建的是由一个共同的 Params 类派生的子类的对象,该共同类本身又是 Pydantic 的 FieldInfo 类的子类。
# Pydantic 的 Field 也会返回一个 FieldInfo 的实例。
# Body 也直接返回 FieldInfo 的一个子类的对象。还有其他一些你之后会看到的类是 Body 类的子类。
# 请记住当你从 fastapi 导入 Query、Path 等对象时,他们实际上是返回特殊类的函数。

#注意每个模型属性如何使用类型、默认值和 Field 在代码结构上和路径操作函数的参数是相同的,区别是用 Field 替换Path、Query 和 Body。

# 添加额外信息¶
# 你可以在 Field、Query、Body 中声明额外的信息。这些信息将包含在生成的 JSON Schema 中。

请求体 - 嵌套模型

from fastapi import FastAPI
from typing import Optional,List,Set,Dict       # 从 typing 导入 List
from pydantic import BaseModel,HttpUrl
app = FastAPI()

#   List字段
class Item(BaseModel):
    name:str
    description:Optional[str] = None
    price:float
    tax:Optional[float] = None
    tags:list = []          #   这将使 tags 成为一个由元素组成的列表。不过它没有声明每个元素的类型。

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

#   具有子类型的 List 字段
class Item(BaseModel):
    name:str
    description:Optional[str] = None
    price:float
    tax:Optional[float] = None
    tags:List[str]=[]       #声明具有子类型的 List

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

#   Set类型
#   Python 具有一种特殊的数据类型来保存一组唯一的元素,即 set。
#   from typing import Optional, Set 导入Set
class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[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 对象。
#
# 上述这些都可以任意的嵌套。
class Image(BaseModel):         # 定义子模型
    url: str
    name: str

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None
    tags:Set[str] = []
    image:Optional[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 获得:
# 1.对被嵌入的模型也适用的编辑器支持(自动补全等)
# 2.数据转换
# 3.数据校验
# 4.自动生成文档

#   特殊的类型和校验
#   除了普通的单一值类型(如 str、int、float 等)外,你还可以使用从 str 继承的更复杂的单一值类型。
#   例如,在 Image 模型中我们有一个 url 字段,我们可以把它声明为 Pydantic 的 HttpUrl,而不是 str:
#   from pydantic import BaseModel, HttpUrl
class Image(BaseModel):         # 定义子模型
    url: HttpUrl                # 声明为 Pydantic 的 HttpUrl,而不是str;;   该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
    name: str

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None
    tags:Set[str] = []
    image:Optional[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


#   带有一组子模型的属性
#   还可以将 Pydantic 模型用作 list、set 等的子类型:
class Image(BaseModel):         # 定义子模型
    url: HttpUrl                # 声明为 Pydantic 的 HttpUrl,而不是str;;   该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
    name: str

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None
    tags:Set[str] = []
    imgae:Optional[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"
#         
#     ]
# 
#   注意 images 键现在具有一组 image 对象是如何发生的。



#   深度嵌套模型
#   可以定义任意深度的嵌套模型
class Image(BaseModel):         # 定义子模型
    url: HttpUrl                # 声明为 Pydantic 的 HttpUrl,而不是str;;   该字符串将被检查是否为有效的 URL,并在 JSON Schema / OpenAPI 文档中进行记录。
    name: str

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

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

@app.post("/offers/")
async def create_offer(offer:Offer):
    return offer
#   注意 Offer 拥有一组 Item 而反过来 Item 又是一个可选的 Image 列表是如何发生的。



#   纯列表请求体
#   如果你期望的 JSON 请求体的最外层是一个 JSON array(即 Python list),则可以在路径操作函数的参数中声明此类型,就像声明 Pydantic 模型一样:images: List[Image]
class Image(BaseModel):
    url: HttpUrl
    name: str

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


#   任意 dict 构成的请求体
#   可以将请求体声明为使用某类型的键和其他类型值的 dict
#   无需事先知道有效的字段/属性(在使用 Pydantic 模型的场景)名称是什么。
#   如果你想接收一些尚且未知的键,这将很有用。
#   在下面的例子中,你将接受任意键为 int 类型并且值为 float 类型的 dict:
@app.post("/index-weights/")
async def create_index_weights(weights: Dict[int, float]):
    return weights
#   请记住 JSON 仅支持将 str 作为键。
# 但是 Pydantic 具有自动转换数据的功能。
# 这意味着,即使你的 API 客户端只能将字符串作为键发送,只要这些字符串内容仅包含整数,Pydantic 就会对其进行转换并校验。
# 然后你接收的名为 weights 的 dict 实际上将具有 int 类型的键和 float 类型的值。

#使用 FastAPI 你可以拥有 Pydantic 模型提供的极高灵活性,同时保持代码的简单、简短和优雅。
# 而且还具有下列好处:
# 编辑器支持(处处皆可自动补全!)
# 数据转换(也被称为解析/序列化)
# 数据校验
# 模式文档
# 自动生成的文档

以上是关于04 FastApi的请求体的主要内容,如果未能解决你的问题,请参考以下文章

fastapi教程翻译(四):Request Body(请求体)

FastAPI 学习之路请求体有多个参数如何处理?

10.FastAPI响应体

FastAPI学习-7.POST请求body-多个参数

FastAPI Web框架 [1.4]

FAST API请求体 - 多个参数