10.FastAPI响应体
Posted Janeh1018
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
在上面的代码中,输入模型为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
以上是关于10.FastAPI响应体的主要内容,如果未能解决你的问题,请参考以下文章