当数据存在时,FastAPI的响应会省略嵌套对象中的字段
我有一个FastAPI的 GET端点,简而言之,它从数据库获取信息,将其整理成一个包含两个字段的对象,这两个字段分别是不同对象的列表,然后返回这个父对象。大多数情况下它运作良好,数据可以找到并几乎按预期返回。然而其中一个对象列表只返回这四个字段中的其中两个,我不确定为什么。稍后我会把相关代码放在最后。
我已经尝试对所有内容使用标准的Pydantic模型,但仍然遇到这个问题,于是我做了一些“调试”,在返回之前把值打印到控制台,所有字段都显示有值,因此我知道字段确实存在且已正确从数据库取回。此外,我还尝试按照这些问题中的建议答案加入 Deeply nested json objects with fastapi and pydantic、Getting nested responses from self related model 的做法,但没有看到任何差异。为测试起见,我还把返回改成只返回父对象中的其中一个列表,而不是整个父对象;这样做时数据全部按预期返回,这进一步证明数据确实存在且被检索。我最后尝试的是手动进行JSON编码并按照文档中的方法返回一个JSON响应,但也仍然没有成功。
Router endpoint
def getComponentDetail(componentId: int):
data = componentService.getComponentDetail(componentId)
return data
Service Method
def getComponentDetail(componentId):
ingredients = componentDataProvider.findIngredientsByComponentId(componentId)
directions = componentDataProvider.findDirectionsByComponentId(componentId)
component = componentDataProvider.findComponentById(componentId)
componentBody = ComponentBody()
componentBody.componentName = component.componentName
componentBody.componentId = component.componentId
componentBody.componentLink = component.originalLink
componentBody.componentNotes = component.componentNotes
componentBody.componentIngredients = ingredients
componentBody.componentDirections = directions
return componentBody
Find component method
def findIngredientsByComponentId(componentId):
with Session(engine) as session:
statement = select(IngredientModel).where(IngredientModel.componentId == componentId)
result = session.exec(statement)
return result.all()
Find ingredients method
def findIngredientsByComponentId(componentId):
with Session(engine) as session:
statement = select(IngredientModel).where(IngredientModel.componentId == componentId)
result = session.exec(statement)
return result.all()
Find directions method
def findDirectionsByComponentId(componentId):
with Session(engine) as session:
statement = select(DirectionModel).where(DirectionModel.componentId == componentId)
result = session.exec(statement)
return result.all()
Component Body Class
class ComponentBody(BaseModel):
componentId: int | None = None
componentName: str | None = None
componentLink: str | None = None
componentNotes: str | None = None
componentIngredients: list[IngredientBody] | None = []
componentDirections: list[DirectionBody] | None = []
def toModel(self):
model = ComponentModel()
model.componentId = self.componentId
model.componentName = self.componentName
model.originalLink = self.componentLink
model.componentNotes = self.componentNotes
return model
Ingredient Body class
class IngredientBody(BaseModel):
ingredientId: int | None = None
ingredientName: str
ingredientMeasurement: float
ingredientUnit: str
def toModel(self):
model = IngredientModel()
model.ingredientId = self.ingredientId
model.ingredientName = self.ingredientName
model.measurement = self.ingredientMeasurement
model.unit = self.ingredientUnit
return model
Direction Body class
class DirectionBody(BaseModel):
directionId: int | None = None
directionOrder: int | None = None
directionText: str | None = None
def toModel(self):
model = DirectionModel()
model.directionId = self.directionId
model.directionText = self.directionText
model.directionOrder = self.directionOrder
return model
我省略了所有导入以便简洁,ingredientModel就是有问题的那个对象,奇怪的是directionBody即使没有添加我试过的那些额外测试也能返回全部三个字段。需要说明的是,ingredientMeasurement和 ingredientUnit是没有返回的两个字段,控制台也没有显示任何错误。
解决方案
我最终搞清楚了。我直接从数据库取出一个模型后就返回了一个响应体,没有进行正确的转换。对另外一个对象之所以能工作,凭我最大的猜测,可能是因为它的响应体与模型之间的属性名完全相同。