Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a child class inherit its base class root validators in pydantic?

I'm making a program in which I'll need to define tons of classes with similar structures. But all of them share one thing in common: There's some conditions their variables must check. So I should define a parent class with the things they all have in common.

On top of that, I want each child class to be able to define a "constant" which cannot be initialized:

I really do not know how to explain myself, so here's an example of very poorly written and non-functional code that illustrates my intentions:

This is a shop with discounts for items over 10€. All books have 10% discount, all phones have 15% discount, and so on.

from pydantic import BaseModel, root_validator

class ShopItems(BaseModel):
    price: float
    discount: float

    def get_final_price(self) -> float:  #All shop item classes should inherit this function
        return self.price * (1 - self.discount/100)

    @root_validator(pre=True)
    def discount_validator(cls, values):  #They should also inherit this one as a validator
        if values["price"] < 10
            values["discount"] = 0
        return values

class Book(ShopItems):
    price: float  #I want to be able to set a different price for any book
    discount = 10


class Phone(ShopItems):
    price: float
    discount = 15


book1 = Book(price=42) #This one should have discount
book2 = Book(8) #This one shouldn't

book1.get_final_price()
book2.get_final_price()

I should also not be able to change the book discount when defining it. The discount value for books should be frozen.

I've tried using dataclasses but i don't really know how to merge pydantic's validators with dataclasses.

like image 495
Aimbot Parce Avatar asked Sep 07 '25 04:09

Aimbot Parce


1 Answers

Validators will be inherited by default. But there are a number of fixes you need to apply to your code:

from pydantic import BaseModel, root_validator

class ShopItems(BaseModel):
    price: float
    discount: float

    def get_final_price(self) -> float:  #All shop item classes should inherit this function
        return self.price * (1 - self.discount/100)

    @root_validator(pre=True)
    def discount_validator(cls, values):  #They should also inherit this one as a validator
        if values["price"] < 10:
            values["discount"] = 0
        return values

class Book(ShopItems):
    discount = 10.


class Phone(ShopItems):
    discount = 15.


book1 = Book(price=42) #This one should have discount
book2 = Book(price=8) #This one shouldn't

print(repr(book1), book1.get_final_price())
print(repr(book2), book2.get_final_price())
Book(price=42.0, discount=10.0) 37.800000000000004
Book(price=8.0, discount=0.0) 8.0
like image 116
madbird Avatar answered Sep 10 '25 04:09

madbird