首页 > 解决方案 > 如何在 pydantic 模型中解析 ObjectId?

问题描述

我正在尝试将 MongoDB 记录解析为 pydantic 模型,但未能这样做ObjectId

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

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')}

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

>>> 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)
>>> 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)

这里肯定有一些我想念的东西。

标签: pythonmongodbparsingobjectidpydantic

解决方案


您的第一个测试用例工作正常。问题在于你如何覆盖ObjectId.

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')))

印刷

who='123456781234567812345678'

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


推荐阅读