Как разобрать 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)

Здесь определенно есть что-то, чего мне не хватает.


person roshii    schedule 27.12.2019    source источник


Ответы (1)


Первый тестовый пример работает нормально. Проблема в том, как вы перезаписываете 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. Итак, data = {"who":ObjectId('123456781234567812345678')} неверен, поскольку он использует ваш дочерний класс ObjectId.

person Tom Wojcik    schedule 27.12.2019