简单解决方案
我认为最简单的解决方案是使用extra = "allow"
设置来配置您的模型(默认情况下设置为extra = "ignore"
)。使用该设置,将任何额外的名称-值对传递给模型构造函数将动态创建具有提供的值和类型的字段在该模型实例上。
这里是一个例子:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Model(BaseModel):
user_name: str
age: int
class Config:
extra = "allow"
@app.post("/home")
def write_home(model: Model) -> Model:
print(model)
return model
现在你可以像这样POST任意的附加数据:
{
"user_name": "string",
"age": 0,
"height": 3.14
}
print
语句的输出是user_name='string' age=0 height=3.14
,响应体与请求完全相同。
潜在风险
在我看来,这里有一个重要的警告,它不仅适用于FastAPI,还适用于Pydantic模型:
使用extra = "allow"
设置时,任何字段名称都将可用。这可能会产生严重的意外后果,因为提供的名称可以覆盖模型命名空间中的现有名称,包括内部属性(例如__fields__
)和预定义方法(例如dict
)。
在FastAPI端点的上下文中,想象一种情况,某人POST
了如下有效载荷:
{
"user_name": "string",
"age": 0,
"dict": 1
}
这将一直正常工作,直到需要调用该实例的dict
方法,这恰好发生在响应形成期间。
换句话说,我们的print(model)
看起来可以正常工作,产生user_name='string' age=0 dict=1
,但尝试从路由处理程序中返回它将使用TypeError: 'int' object is not callable
导致服务器崩溃。
这只是一个例子,但这应该说明为什么如果您不正确处理它,则可能很危险或至少有问题。
其他注意事项
还有一些小的注意事项需要您知道:
- 这可能是显而易见的,但任何这些额外字段值上都不会进行验证。在通过配置(或默认)JSON解码器进行解析后,它们将原样分配给模型实例。
- OpenAPI文档当然无法显示这些字段是作为接受请求体模式的一部分还是包含在响应模型模式中。