Oskar Sharipov
Oskar Sharipov

Reputation: 35

pydantic.BaseModel: classmethod of a parent

How can I call a classmethod of a parent?

I need to import ORM-model to a Pydantic model. I know there is a pydantic.BaseModel.from_orm but it won't do a work in my case because I have fields which must be converted manually. For example, I have a phone_number field which cannot be represented as str itself. That's why I'm writing "my-own-another-one-from-orm-method".

Let's forget about ORMs. I've drawn an example which I expect to work:

>>> class Parent(BaseModel):
...     a: int
...     @classmethod
...     def import_(cls, a: int) -> "Parent":
...         new = cls(a=a)
...         return new
>>> class Child(Parent):
...     b: int
...     @classmethod
...     def import_(cls, a: int, b: int) -> "Child":
...         new = cls(b=b, **super().import_(a).dict())
...         return new
>>> Child.import_(a=1, b=2)

Unfortunately, it fails. As I understand an error, super() is calling import_ from a Child for some reason. Well, maybe I don't understand an error correctly but there is:

pydantic.error_wrappers.ValidationError: 1 validation error for Child
b
  field required (type=value_error.missing)

1 validation error for Child
b
  field required (type=value_error.missing)

What should I write to let that example exist correctly?

Upvotes: 1

Views: 3495

Answers (1)

alex_noname
alex_noname

Reputation: 32143

In order to do what you want you need to explicitly use the base class name for calling Parent.import_(a) method of it, because when super() is used cls would be set to child class(actual object type).

class Child(Parent):
    b: int

    @classmethod
    def import_(cls, a: int, b: int) -> "Child":
        parent = Parent.import_(a).dict()
        new = cls(b=b, **parent)
        return new

Upvotes: 2

Related Questions