10.FastAPI响应体

农村四月闲人少,勤学苦攻把名扬。这篇文章主要讲述10.FastAPI响应体相关的知识,希望能为你提供帮助。
10.FastAPI响应体FastAPI支持声明响应体模型进行响应数据的处理。 可以在任意路由操作中使用 response_model 参数来声明用于响应的模型:

  • @app.get()
  • @app.post()
  • @app.put()
  • @app.delete()
  • 等等。
response_model是装饰器方法(get,post 等)的一个参数,而不是路由操作函数的参数;其类型与 Pydantic 模型属性所声明的类型相同,因此它可以是一个 Pydantic 模型,但也可以是一个由 Pydantic 模型组成的 list,例如 List[Item]。
在FastAPI 中,使用 response_model 的作用:
  • 将输出数据转换为其声明的类型。
  • 校验数据。
  • 在 OpenAPI 的路径操作中为响应添加一个 JSON Schema。
  • 并在自动生成文档系统中使用。
  • 会将输出数据限制在该模型定义内。
10.1响应模型代码示例:
from fastapi import FastAPI

from pydantic import BaseModel


app = FastAPI()


class UsrIn(BaseModel):

name: str

sex: str

acc: str

pwd: str


class UsrOut(BaseModel):

name: str

sex: str

acc: str



@app.post(path=/add_a_usr, response_model=UsrOut)

async def add_a_usr(usr: UsrIn):

return usr

【10.FastAPI响应体】在上面的代码中,输入模型为UsrIn,输出模型为UsrOut,通过输出模型来屏蔽pwd字段的输出。执行请求:
curl -H "Content-Type: application/json; " -X POST -d "\\"name\\":\\"zhaomm\\",\\"sex\\":\\"woman\\",\\"acc\\":\\"zhaomm\\",\\"pwd\\":\\"Zhao68641018\\"" http://127.0.0.1:8000/add_a_usr


"name":"zhaomm",

"sex":"woman",

"acc":"zhaomm"


10.2响应模型默认值在FastAPI中,响应模型也可以具有默认值。
代码示例:
from fastapi import FastAPI

from fastapi import Body

from typing import Optional

from typing import List

from pydantic import BaseModel


app = FastAPI()


class ProductOut(BaseModel):

id: str = Body(...)

name: str = Body(...)

price: Optional[float] = Body(10.0)

desc: Optional[str] = Body(None)



@app.get(path=/find_products, response_model=List[ProductOut])

async def find_products():

products = [

id: p1, name: 玫瑰花,

id: p2, name: 百合花, price: 12.8,

id: p3, name: 月季花, price: 19.8, desc: 月季花

]

return products

执行请求:
curl http://127.0.0.1:8000/find_products

[


"id":"p1",

"name":"玫瑰花",

"price":10.0,

"desc":null

,

"id":"p2",

"name":"百合花",

"price":12.8,

"desc":null

,

"id":"p3",

"name":"月季花",

"price":19.8,

"desc":"月季花"


]

从上面的代码执行结果可以看出:当在实际输出中没有定义对应的字段属性值时,使用响应模型的默认值输出。如果希望响应结果中不输出默认值,仅输出实际数据,则可以在 可以设置路由操作装饰器的 response_model_exclude_unset 参数为真,下面代码在路由中增加该参数,代码如下:
from fastapi import FastAPI

from fastapi import Body

from typing import Optional

from typing import List

from pydantic import BaseModel


app = FastAPI()


class ProductOut(BaseModel):

id: str = Body(...)

name: str = Body(...)

price: Optional[float] = Body(10.0)

desc: Optional[str] = Body(None)



@app.get(path=/find_products, response_model=List[ProductOut], response_model_exclude_unset=True)

async def find_products():

products = [

id: p1, name: 玫瑰花,

id: p2, name: 百合花, price: 12.8,

id: p3, name: 月季花, price: 19.8, desc: 月季花

]

return products

执行请求:
curl http://127.0.0.1:8000/find_products

[


"id":"p1",

"name":"玫瑰花"

,

"id":"p2",

"name":"百合花",

"price":12.8

,

"id":"p3",

"name":"月季花",

"price":19.8,

"desc":"月季花"


]

在以上情况下,如果实际数据值与默认值相同,那么FastAPI仍然会输出,也就是说,当设置response_model_exclude_unset=True时,其输出是按照实际值输出的。下面将代码id: p2, name: 百合花, price: 12.8中的price字段值修改为10.0,然后执行请求:
curl http://127.0.0.1:8000/find_products

[


"id":"p1",

"name":"玫瑰花"

,

"id":"p2",

"name":"百合花",

"price":10.0

,

"id":"p3",

"name":"月季花",

"price":19.8,

"desc":"月季花"


]

从上面的执行结果可以看出:虽然实际数据值与默认值相同,但仍然会输出。如果此时,不希望输出与默认值相同的数据值,可以设置 response_model_exclude_defaults参数为True,代码片段如下:
class ProductOut(BaseModel):

id: str = Body(...)

name: str = Body(...)

price: Optional[float] = Body(10.0)

desc: Optional[str] = Body(None)


@app.get(path=/find_products, response_model=List[ProductOut], response_model_exclude_defaults=True)

async def find_products():

products = [

id: p1, name: 玫瑰花,

id: p2, name: 百合花, price: 10.0,

id: p3, name: 月季花, price: 19.8, desc: 月季花

]

return products

执行请求:
curl http://127.0.0.1:8000/find_products

[


"id":"p1",

"name":"玫瑰花"

,

"id":"p2",

"name":"百合花"

,

"id":"p3",

"name":"月季花",

"price":19.8,

"desc":"月季花"


]

在上面的执行结果中:"id":"p2","name":"百合花"没有输出price字段的实际数据值,因为与默认值相同。
另外还有一个装饰器参数: response_model_exclude_none,如果设置该参数为True,则表示在响应模型中不输出None值。代码片段如下:
@app.get(path=/find_products, response_model=List[ProductOut], response_model_exclude_none=True)

async def find_products():

products = [

id: p1, name: 玫瑰花,

id: p2, name: 百合花, price: 10.0,

id: p3, name: 月季花, price: 19.8, desc: 月季花

]

return products

执行请求:
curl http://127.0.0.1:8000/find_products

[


"id":"p1",

"name":"玫瑰花",

"price":10.0

,

"id":"p2",

"name":"百合花",

"price":10.0

,

"id":"p3",

"name":"月季花",

"price":19.8,

"desc":"月季花"


]

10.3显式声明响应模型的字段可以使用装饰器参数response_model_include 和 response_model_exclude来显式指明包含或者排除的字段,这两个参数接受由字符串组成的set类型,也可以使用list或tuple,但使用list或tuple最终会转换为set类型。
在python中,set类型使用一组花括号定义,如:sex, name。
代码示例:
@app.get(path=/find_products, response_model=List[ProductOut], response_model_include=price, desc)

async def find_products():

products = [

id: p1, name: 玫瑰花,

id: p2, name: 百合花, price: 10.0,

id: p3, name: 月季花, price: 19.8, desc: 月季花

]

return products

执行请求:
curl http://127.0.0.1:8000/find_products

[


"price":10.0,

"desc":null

,

"price":10.0,

"desc":null

,

"price":19.8,

"desc":"月季花"


]

10.4响应模型Union在FastAPI中,响应模型可以设置为多个类型的Union,响应为多种类型中的一种;定义该类型使用标准的Python类型提示typing.Union,原则上应该是先使用详细的类型,然后使用粗略的类型。代码示例:
from typing import Union

from fastapi import FastAPI

from pydantic import BaseModel


app = FastAPI()


class BaseItem(BaseModel):

description: str

type: str


class CarItem(BaseItem):

type = "car"

length: int


class PlaneItem(BaseItem):

type = "plane"

size: int


items =

"item1": "description": "All my friends drive a low rider", "type": "car", "length": 200,

"item2":

"description": "Music is my aeroplane, its my aeroplane",

"type": "plane",

"size": 5,

,




@app.get("/items/item_id", response_model=Union[PlaneItem, CarItem])

async def read_item(item_id: str):

return items[item_id]

执行请求:
curl http://127.0.0.1:8000/items/item1


"description":"All my friends drive a low rider",

"type":"car",

"length":200


C:\\Users\\Administrator> curl http://127.0.0.1:8000/items/item2


"description":"Music is my aeroplane, its my aeroplane",

"type":"plane",

"size":5


10.5任意 dict 构成的响应在FastAPI中,如果事先不确定返回值的键名称,但可以确定返回的数据类型,那么,可以使用只包含类型的dict作为响应模型,使用 typing.Dict。示例代码如下:
from fastapi import FastAPI

from typing import Dict


app = FastAPI()


@app.get(path=/test, response_model=Dict[str, int])

async def test():

return foo: 20

执行请求:
curl http://127.0.0.1:8000/test

"foo":20




    推荐阅读