首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在pydantic模型中解析ObjectId?

如何在pydantic模型中解析ObjectId?
EN

Stack Overflow用户
提问于 2019-12-28 00:28:35
回答 3查看 6.3K关注 0票数 9

我正在尝试将MongoDB记录解析为pydantic模型,但无法为ObjectId执行此操作

据我所知,我需要为ObjectId设置验证器,并尝试使用ObjectId扩展ObjectId类并将validator装饰器添加到我的类中。我这样做了。

代码语言:javascript
复制
from pydantic import BaseModel, validator
from bson.objectid import ObjectId


class ObjectId(ObjectId):
    pass
    @classmethod
    def __get_validators__(cls):
        yield cls.validate
    @classmethod
    def validate(cls, v):
        if not isinstance(v, ObjectId):
            raise TypeError('ObjectId required')
        return str(v)


class User(BaseModel):
    who: ObjectId


class User1(BaseModel):
    who: ObjectId
    @validator('who')
    def validate(cls, v):
        if not isinstance(v, ObjectId):
            raise TypeError('ObjectId required')
        return str(v)

data = {"who":ObjectId('123456781234567812345678')}

不幸的是,这两个“解决方案”都失败了,如下所示:

代码语言:javascript
复制
>>> test = User(**data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydantic/main.py", line 274, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for User
id
  field required (type=value_error.missing)
代码语言:javascript
复制
>>> test = User1(**data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pydantic/main.py", line 274, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for User1
who
  ObjectId required (type=type_error)

这里肯定有我遗漏的东西。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-28 01:05:48

您的第一个测试用例运行良好。问题在于如何重写ObjectId

代码语言:javascript
复制
from pydantic import BaseModel
from bson.objectid import ObjectId as BsonObjectId


class PydanticObjectId(BsonObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not isinstance(v, BsonObjectId):
            raise TypeError('ObjectId required')
        return str(v)


class User(BaseModel):
    who: PydanticObjectId


print(User(who=BsonObjectId('123456781234567812345678')))

打印

代码语言:javascript
复制
who='123456781234567812345678'

只有pydantic才应该使用pydantic类型。Mongo将为您提供bsons。所以用真正的ObjectId实例化你的数据。所以data = {"who":ObjectId('123456781234567812345678')}是错误的,因为它使用了您的子类ObjectId。

票数 17
EN

Stack Overflow用户

发布于 2021-07-29 17:43:58

另一种方法是使用pydantic,我从另一个来源发现它很有用,它是:

在models文件夹中定义一个名为PyObjectId.py的文件。

代码语言:javascript
复制
from pydantic import BaseModel, Field as PydanticField
from bson import ObjectId

class PyObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate
    @classmethod
    def validate(cls, v):
        if not ObjectId.is_valid(v):
            raise ValueError("Invalid objectid")
        return ObjectId(v)
    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")

然后,您可以在任何对象文件中使用它,如下面的users.py

代码语言:javascript
复制
from models.PyObjectId import PyObjectId
from pydantic import BaseModel, Field as PydanticField
from bson import ObjectId
class Users(BaseModel):
    id: PyObjectId = PydanticField(default_factory=PyObjectId, alias="_id")
    class Config:
        allow_population_by_field_name = True
        arbitrary_types_allowed = True #required for the _id 
        json_encoders = {ObjectId: str}
票数 1
EN

Stack Overflow用户

发布于 2021-10-04 06:19:36

这段代码帮助你使用json编码器。

代码语言:javascript
复制
from bson import ObjectId
from pydantic import BaseModel


class ObjId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

@classmethod
def validate(cls, v: str):
    try:
        return cls(v)
    except InvalidId:
        raise ValueError("Not a valid ObjectId")


class Foo(BaseModel):
    object_id_field: ObjId = None

    class Config:
        json_encoders = {
            ObjId: lambda v: str(v),
        }



obj = Foo(object_id_field="60cd778664dc9f75f4aadec8")
print(obj.dict())
# {'object_id_field': ObjectId('60cd778664dc9f75f4aadec8')}
print(obj.json())
# {'object_id_field': '60cd778664dc9f75f4aadec8'}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59503461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档