欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > Python FastApi(7):请求体

Python FastApi(7):请求体

2025/4/1 17:11:05 来源:https://blog.csdn.net/qq_40298351/article/details/146556956  浏览:    关键词:Python FastApi(7):请求体

1 多个参数

1.1 混合使用 PathQuery 和请求体参数

        首先,毫无疑问地,你可以随意地混合使用 PathQuery 和请求体参数声明,FastAPI 会知道该如何处理。你还可以通过将默认值设置为 None 来将请求体参数声明为可选参数:

from typing import Annotatedfrom fastapi import FastAPI, Path
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],q: str | None = None,item: Item | None = None,
):results = {"item_id": item_id}if q:results.update({"q": q})if item:results.update({"item": item})return results

        请注意,在这种情况下,将从请求体获取的 item 是可选的。因为它的默认值为 None

1.2 多个请求体参数

        在上面的示例中,路径操作将期望一个具有 Item 的属性的 JSON 请求体,就像:

{"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2
}

        但是你也可以声明多个请求体参数,例如 item 和 user

from fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneclass User(BaseModel):username: strfull_name: str | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User):results = {"item_id": item_id, "item": item, "user": user}return results

        在这种情况下,FastAPI 将注意到该函数中有多个请求体参数(两个 Pydantic 模型参数)。因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于以下内容的请求体:

{"item": {"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2},"user": {"username": "dave","full_name": "Dave Grohl"}
}

        FastAPI 将自动对请求中的数据进行转换,因此 item 参数将接收指定的内容,user 参数也是如此。它将执行对复合数据的校验,并且像现在这样为 OpenAPI 模式和自动化文档对其进行记录。

1.3 请求体中的单一值

        与使用 Query 和 Path 为查询参数和路径参数定义额外数据的方式相同,FastAPI 提供了一个同等的 Body。例如,为了扩展先前的模型,你可能决定除了 item 和 user 之外,还想在同一请求体中具有另一个键 importance

        如果你就按原样声明它,因为它是一个单一值,FastAPI 将假定它是一个查询参数。但是你可以使用 Body 指示 FastAPI 将其作为请求体的另一个键进行处理。

from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Noneclass User(BaseModel):username: strfull_name: str | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User, importance: Annotated[int, Body()]
):results = {"item_id": item_id, "item": item, "user": user, "importance": importance}return results

        在这种情况下,FastAPI 将期望像这样的请求体:

{"item": {"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2},"user": {"username": "dave","full_name": "Dave Grohl"},"importance": 5
}

        同样的,它将转换数据类型,校验,生成文档等。

1.4 多个请求体参数和查询参数

        当然,除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。由于默认情况下单一值被解释为查询参数,因此你不必显式地添加 Query,你可以仅执行以下操作:

q: str = None
@app.put("/items/{item_id}")
async def update_item(*,item_id: int,item: Item,user: User,importance: Annotated[int, Body(gt=0)],q: str | None = None,
):

   Body 同样具有与 QueryPath 以及其他后面将看到的类完全相同的额外校验和元数据参数。 

1.5 嵌入单个请求体参数

        假设你只有一个来自 Pydantic 模型 Item 的请求体参数 item。默认情况下,FastAPI 将直接期望这样的请求体。但是,如果你希望它期望一个拥有 item 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 Body 参数 embed

item: Item = Body(embed=True)
from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):results = {"item_id": item_id, "item": item}return results

        在这种情况下,FastAPI 将期望像这样的请求体:

{"item": {"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2}
}

        而不是:

{"name": "Foo","description": "The pretender","price": 42.0,"tax": 3.2
}

2 字段

        与在路径操作函数中使用 QueryPath 、Body 声明校验与元数据的方式一样,可以使用 Pydantic 的 Field 在 Pydantic 模型内部声明校验和元数据。首先,从 Pydantic 中导入 Field

from typing import Annotatedfrom fastapi import Body, FastAPI
from pydantic import BaseModel, Field

        然后,使用 Field 定义模型的属性:

class Item(BaseModel):name: strdescription: str | None = Field(default=None, title="The description of the item", max_length=300)price: float = Field(gt=0, description="The price must be greater than zero")tax: float | None = None@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):results = {"item_id": item_id, "item": item}return results

   模型属性的类型、默认值及 Field 的代码结构与路径操作函数的参数相同,只不过是用 Field 替换了PathQueryBody

3 嵌套模型

        使用 FastAPI,你可以定义、校验、记录文档并使用任意深度嵌套的模型(归功于Pydantic)。

3.1 List 字段

        你可以将一个属性定义为拥有子元素的类型。例如 Python list

class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: list = []

        这将使 tags 成为一个由元素组成的列表。不过它没有声明每个元素的类型。Python 有一种特定的方法来声明具有子类型的列表:

from typing import List, Unionfrom fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: Union[str, None] = Noneprice: floattax: Union[float, None] = Nonetags: List[str] = []

        这完全是用于类型声明的标准 Python 语法。对具有子类型的模型属性也使用相同的标准语法。因此,在我们的示例中,我们可以将 tags 明确地指定为一个「字符串列表」。

3.2 Set 类型

        Python 具有一种特殊的数据类型来保存一组唯一的元素,即 set。然后我们可以导入 Set 并将 tag 声明为一个由 str 组成的 set

class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()

        这样,即使你收到带有重复数据的请求,这些数据也会被转换为一组唯一项。而且,每当你输出该数据时,即使源数据有重复,它们也将作为一组唯一项输出。并且还会被相应地标注 / 记录文档。

3.3 嵌套模型

        Pydantic 模型的每个属性都具有类型。但是这个类型本身可以是另一个 Pydantic 模型。因此,你可以声明拥有特定属性名称、类型和校验的深度嵌套的 JSON 对象。上述这些都可以任意的嵌套。例如,我们可以定义一个 Image 模型:

class Image(BaseModel):url: strname: str

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

class Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()image: Image | None = None

        这意味着 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 获得:

  • 对被嵌入的模型也适用的编辑器支持(自动补全等)
  • 数据转换
  • 数据校验
  • 自动生成文档

3.4 特殊的类型和校验

        除了普通的单一值类型(如 strintfloat 等)外,你还可以使用从 str 继承的更复杂的单一值类型。例如,在 Image 模型中我们有一个 url 字段,我们可以把它声明为 Pydantic 的 HttpUrl,而不是 str

from fastapi import FastAPI
from pydantic import BaseModel, HttpUrlapp = FastAPI()class Image(BaseModel):url: HttpUrlname: str

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

3.5 带有一组子模型的属性

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

class Image(BaseModel):url: HttpUrlname: strclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()images: list[Image] | None = None

        这将期望(转换,校验,记录文档等)下面这样的 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"}]
}

3.6 深度嵌套模型

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

class Image(BaseModel):url: HttpUrlname: strclass Item(BaseModel):name: strdescription: str | None = Noneprice: floattax: float | None = Nonetags: set[str] = set()images: list[Image] | None = Noneclass Offer(BaseModel):name: strdescription: str | None = Noneprice: floatitems: list[Item]

3.7 纯列表请求体

        如果你期望的 JSON 请求体的最外层是一个 JSON array(即 Python list),则可以在路径操作函数的参数中声明此类型,就像声明 Pydantic 模型一样:

images: List[Image]
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrlapp = FastAPI()class Image(BaseModel):url: HttpUrlname: str@app.post("/images/multiple/")
async def create_multiple_images(images: list[Image]):return images

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com