FastAPI(10)- 详解 Body

前言

  • 上一篇有讲到将参数类型指定为 Pydantic Model,这样 FastAPI 会解析它为一个 Request Body
  • 那单类型(int、float、str、bool...)参数可以成为 Request Body 的一部分吗?答案是可以的
  • 通过 Body 函数即可完成,和 Path、Query 有异曲同工之妙

 

文章跳转

Query

Path

Request Body

 

Body

  • 主要作用:可以将单类型的参数成为 Request Body 的一部分,即从查询参数变成请求体参数
  • 和 Query、Path 提供的额外校验、元数据是基本一致的(多了个 embed 参数,最后讲解)

FastAPI(10)- 详解 Body

 

Body 的简单栗子

from typing import Optional

import uvicorn
from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


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


class User(BaseModel):
    username: str
    full_name: Optional[str] = None


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


if __name__ == "__main__":
    uvicorn.run(app="8_Body:app", host="127.0.0.1", port=8080, reload=True, debug=True)

  

期望得到的 Request Body

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

Request Body 中多了个 importance

 

正确传参的请求结果

FastAPI(10)- 详解 Body

 

查看 Swagger API 文档

FastAPI(10)- 详解 Body

 

Query、Path、Body 终极混用

from typing import Optional

import uvicorn
from fastapi import Body, FastAPI, Path, Query
from pydantic import BaseModel

app = FastAPI()


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


class User(BaseModel):
    username: str
    full_name: Optional[str] = None


@app.put("/item_all/{item_id}")
async def update_item(
        *,
        item_id: int = Path(default=..., description="路径参数", gt=0, lt=10),
        address: str = Query(default=None, description="查询参数", max_length=10),
        item: Item,
        user: User,
        importance: int = Body(default=..., description="请求体", ge=1, le=5)
):
    results = {
        "item_id": item_id,
        "address": address,
        "item": item,
        "user": user,
        "importance": importance
    }
    return results

 

正确传参的请求结果

FastAPI(10)- 详解 Body

 

查看 Swagger API 文档

FastAPI(10)- 详解 Body

 

Body() 中的 embed 参数

为什么要讲这个 embed 参数

当函数只有一个参数指定了 Pydantic Model 且没有其他 Body 参数时,传参的时候请求体可以不指定参数名

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


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

 

期望得到的请求体

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

默认并不需要指定 item 为字段名

 

那假设想指定 item 为请求体的字段名呢?就是通过 embed 参数达到目的了

 

实际代码

from typing import Optional

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()

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


@app.put("/items/{item_id}")
async def update_item(
        *,
        item_id: int,
        # 将 embed 设置为 True
        item: Item = Body(..., embed=True)):
    results = {"item_id": item_id, "item": item}
    return results

 

期望得到的请求体

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

 

正确传参的请求结果

FastAPI(10)- 详解 Body

 

还是不传 item 字段的请求结果

FastAPI(10)- 详解 Body

 

查看 Swagger API 文档

FastAPI(10)- 详解 Body

 

上一篇:【C++17】std::optional


下一篇:010Java8新特性003Optional类