web-dev-qa-db-ja.com

pydanticモデルでObjectIdを解析する方法は?

MongoDBレコードをpydanticモデルに解析しようとしていますが、ObjectIdの場合は失敗します

私が理解したことから、ObjectIdのバリデーターをセットアップする必要があり、ObjectIdクラスを拡張し、ObjectIdを使用してvalidatorデコレーターをクラスに追加しようとしました。私は次のようにしました。

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)

ここで私が見逃していることは間違いありません。

3
roshii

最初のテストケースは正常に機能します。問題は、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のみを使用してください。 Mongoはbsons ObjectIdを提供します。したがって、実際のObjectIdを使用してデータをインスタンス化します。したがって、子ObjectIdクラスを使用するため、data = {"who":ObjectId('123456781234567812345678')}は間違っています。

2
Tom Wojcik