Jenia Be Nice Please
Jenia Be Nice Please

Reputation: 2693

Constructor and Pydantic

I want to create a Pydantic class with a constructor that does some math on inputs and set the object variables accordingly:

class PleaseCoorperate(BaseModel):
    self0: str
    next0: str

    def __init__(self, page: int, total: int, size: int):
        # Do some math here and later set the values
        self.self0 = ""
        self.next0 = ""
    

But when I try to actually use that class page = PleaseCoorperate(0, 1, 50) I get this error:

main_test.py:16: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
main.py:46: in __init__
    self.self0 = ""
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   AttributeError: __fields_set__

What is happening here? Can I not use constructors on a Pydantic class?

Upvotes: 11

Views: 12795

Answers (2)

amiasato
amiasato

Reputation: 1020

You are not invoking the BaseModel constructor, and thus, you are skipping all the pydantic magic that turns class variables into attributes. This:

class PleaseCoorperate(BaseModel):
    self0: str
    next0: str

    def __init__(self, page: int, total: int, size: int):
        # Do some math here and later set the values
        self0 = ""
        next0 = ""
        super().__init__(self0=self0, next0=next0)

should do the trick. However, may I suggest a better option that doesn't override the much excellent default constructor from pydantic with a class method:

class PleaseCoorperate(BaseModel):
    self0: str
    next0: str

    @classmethod
    def custom_init(cls, page: int, total: int, size: int):
        # Do some math here and later set the values
        self0 = ""
        next0 = ""
        return cls(self0=self0, next0=next0)

x = PleaseCoorperate.custom_init(10, 10, 10)

Upvotes: 15

PaxPrz
PaxPrz

Reputation: 1928

You can use pydantic validators. These are perfect candidate for your solution.

from pydantic import BaseModel, validator

class PleaseCoorperate(BaseModel):
    self0: str
    next0: str

    @validator('self0')
    def self0_math_test(cls, v):  # v set the values passed for self0
        # your math here
        return new_self0

    @validator('next0', always=True)  # always if you want to run it even when next0 is not passed (optional)
    def next0_must_have(cls, v, values, **kwargs):  # values sets other variable values
        # your math here
        return new_next0

Validators Documentation: here

Upvotes: 2

Related Questions