学习,记录一下,方便回顾。
请求体 - 字段
# 与使用 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 模型提供的极高灵活性,同时保持代码的简单、简短和优雅。
# 而且还具有下列好处:
# 编辑器支持(处处皆可自动补全!)
# 数据转换(也被称为解析/序列化)
# 数据校验
# 模式文档
# 自动生成的文档