赞
踩
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。
并在自动生成文档系统中使用。
会将输出数据限制在该模型定义内。
代码示例:
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" }
在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":"月季花" } ]
可以使用装饰器参数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":"月季花" } ]
在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, it's 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, it's my aeroplane", "type":"plane", "size":5 }
在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}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。