FastAPI(Pydantic)中如何保持请求体结构与BaseModel定义一致?
问题
在POST请求中,希望无论用户传入什么内容,请求体都严格遵循BaseModel的定义。
示例BaseModel定义如下:
from typing import Optional from pydantic import BaseModel class Address(BaseModel): city: Optional[str] state: Optional[str] pinCode: Optional[str] class User_ReqModel(BaseModel): name: str mobile: Optional[str] address: Optional[Address]
当请求体为{"name": "Amit Pathak"}时,访问User_ReqModel.address.city会报错——因为请求体中未传入address,此时该字段值为None,无法直接访问子属性。
目前有两种规避方式,但均存在不足:
- 对空值逐一检查不可行,因为请求体结构较大,无法覆盖所有属性;
- 转成
dict()后用.get('key', {})取值,这种方式不够简洁,希望避免。
期望实现:当请求体为{"name": "Amit Pathak"}时,自动生成如下格式的实例:
{ "name": "Amit Pathak", "mobile": null, "address": { "city": null, "state": null, "pinCode": null } }
解决方案
只需修改BaseModel的字段定义,给嵌套模型字段设置默认工厂函数,让缺失字段时自动生成空模型实例,同时给Optional类型字段显式设置默认值None(Pydantic对Optional类型会自动处理,但显式设置更清晰)。
修改后的代码
from typing import Optional from pydantic import BaseModel, Field class Address(BaseModel): city: Optional[str] = None state: Optional[str] = None pinCode: Optional[str] = None class User_ReqModel(BaseModel): name: str mobile: Optional[str] = None # 用default_factory自动生成空的Address实例 address: Address = Field(default_factory=Address)
关键说明
Address的每个字段显式设置None为默认值,确保未传入时自动填充为null;- 将
User_ReqModel的address字段类型从Optional[Address]改为Address,并通过default_factory=Address指定:当该字段缺失时,自动创建一个所有子字段为None的Address实例; - 处理后,即使请求体未传入
mobile或address,实例也会自动填充对应默认值,直接访问user.address.city不会报错。
如果需要允许用户显式传入"address": null,可以保留Optional类型并搭配默认工厂:
class User_ReqModel(BaseModel): name: str mobile: Optional[str] = None address: Optional[Address] = Field(default_factory=Address)
这样既支持用户传入null,也会在字段缺失时自动生成空的Address实例。
内容的提问来源于stack exchange,提问作者Amit Pathak
相关产品推荐
相关产品推荐

