【问题标题】:What is a good way to mutate object attribute from id to actual id reference将对象属性从 id 变为实际 id 引用的好方法是什么
【发布时间】:2021-08-17 17:10:00
【问题描述】:

我正在制作一个带有端点的 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 的实例?

【问题讨论】:

    标签: python pymongo fastapi pydantic


    【解决方案1】:

    至少有两种方法可以实现您的目标。

    首先是让 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
    

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

    【讨论】:

    • 谢谢这是完美的!
    猜你喜欢
    • 1970-01-01
    • 2015-10-27
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-27
    • 2011-11-16
    相关资源
    最近更新 更多