将对象属性从id改为实际id引用的好方法是什么?



我正在制作一个带有端点的API,它应该返回一个像这样的对象

{
'id': 'asdqwe123randomnessxxyyzz',
'title': 'some title',
'owner': {
'id': 'qwersdaf4132otherrandomness',
'name': 'some name',
},
}

,在数据库中对象看起来像这样

{
'id': 'asdqwe123randomnessxxyyzz',
'title': 'some title',
'owner_id': 'qwersdaf4132otherrandomness',
}

我正在为我的API使用pydantic模型,目前我正在返回这样的对象

return [Object(**x) for x in mongo_db_column.find()]

其中x是来自数据库的json

Object的类是这样的:

from pydantic import Basemodel, Optional
class Object(Basemodel):
id: Optional[str]
title: str
owner_id: str

和所有者类看起来像这样:

class Owner(Basemodel):
id: Optional[str]
name: str

所以我的问题是,如果有可能使用Basemodel的一些方法来实例化它,以便owner_id将转换为Owner的实例?

至少有两种方法可以达到你的目标。

首先是保持pydantic模型"哑巴";(意味着它们不以任何方式绑定到数据库),并使用数据库中已经聚合的数据初始化它们。

您将不得不重写您的模型,以便Object模型引用Owner

from typing import Optional
from pydantic import BaseModel

class Owner(BaseModel):
id: Optional[str]
name: str

class Object(BaseModel):
id: Optional[str]
title: str
owner: Owner

如果你已经汇总了数据,那么:

data = {
'id': 'asdqwe123randomnessxxyyzz',
'title': 'some title',
'owner': {
'id': 'qwersdaf4132otherrandomness',
'name': 'some name',
},
}
Object(**data)  # this would produce desired value

您也可以从Basemodel字段的预验证中加载引用的所有者:

from typing import Optional
from pydantic import BaseModel, Field, validator

class Owner(BaseModel):
id: Optional[str]
name: str

class Object(BaseModel):
id: Optional[str]
title: str
owner: Owner = Field(..., alias='owner_id')
@validator('owner', pre=True)
def load_owner(cls, owner_id):
if isinstance(owner_id, str):
# perform loading from owner collection
# e.g. owner = owner_collection.find_one({'id': owner_id})
return owner
return owner_id

这样你的代码应该产生期望的值。