【问题标题】:How to use values from list to validate some calculations in pydantic BaseModel?如何使用列表中的值来验证 pydantic BaseModel 中的一些计算?
【发布时间】:2021-02-10 13:35:12
【问题描述】:

我正在使用 Pydantic root_validator 在我的模型中执行一些计算:

class ProductLne(BaseModel):
    qtt_line: float = 0.00
    prix_unite: float = 0.00
    so_total_ht: float = 0.00
    
    class Config:
        validate_assignment = True

    @root_validator()
    def calculat_so_totals(cls, values):
      values["so_total_ht"] = values.get("qtt_line")*values.get("prix_unite")
    
    return values

class Bon(BaseModel):
    articles: List[ProductLne] = []
    total_ht: float = 0.00

    class Config:
        validate_assignment = True

    @root_validator()
    def set_total_ht(cls, values):
        for item in values.get('articles'):
            values['total_ht'] += item.so_total_ht
        return values

一些数据

 item_line1 = ProductLne(qtt_line=10, prix_unite=10.00)
 item_line2 = ProductLne(qtt_line=10, prix_unite=12.00)
 bon1 = Bon()
 bon1.articles.append(item_line1)
 bon1.articles.append(item_line2)

运行时

 print(bon1.total_ht)

我得到:0.0,O.OO 想要220

如何让这个函数返回正确的值?

【问题讨论】:

  • 错误在你的 for 循环中。您正在尝试从 cls 参数访问 ProductLne 数据,但它不包含任何数据。查看我的回答了解更多详情。

标签: python pydantic


【解决方案1】:

我发现了你的问题。这是因为您试图访问 cls 上不存在的数据,并且您从值访问数据的方式是错误的。首先,您必须在某个时刻通过ProductLneBon 传递数据。因此,我更改了您的代码以在初始化时设置 ProductLne 的值,然后在 Bon 初始化时在验证器中对其进行初始化。然后运行Bon(),我相信这就是你想要完成的。您仍然可以通过脚本传递数据,我只是不知道您的脚本是什么样的。示例(简化):

class ProductLne(BaseModel):
    qtt_line: float = 1.0
    so_total_ht: float = 1.0

    @root_validator()
    def calculat_so_totals(cls, values):
        values["so_total_ht"] = values.get("qtt_line")
        return values


class Bon(BaseModel):
    articles: List[ProductLne] = []
    total_ht: float = 0.0

    @root_validator()
    def set_total_ht(cls, values):
        product_line = ProductLne()
        values["articles"].append(product_line)
        for item in values.get("articles"):
           values["total_ht"] += item.qtt_line
        return values

【讨论】:

    【解决方案2】:

    我不知道这是不是很好,但我得到了我想要的

    from pydantic import BaseModel, root_validator, Field
    from typing import List
    from typing import TYPE_CHECKING, Union
    if TYPE_CHECKING:
        from pydantic.typing import DictStrAny
    
    
    class PropertyBaseModel(BaseModel):
    
    @classmethod
    def get_properties(cls):
        return [
            prop for prop in dir(cls)
            if isinstance(getattr(cls, prop), property) and prop not in ("__values__", "fields")
        ]
    
    def dict(self, *args, **kwargs) -> 'DictStrAny':
        self.__dict__.update({prop: getattr(self, prop) for prop in self.get_properties()})
    
        return super().dict(*args, **kwargs)
    
    
    class ProductLne(PropertyBaseModel):
        prix: float = 0.00
        qtt_line: float = 0.0
    
        @property
        def so_total_ht(self) -> float:
            return self.qtt_line * self.prix
    
    
    class Bon(BaseModel):
        articles: List[ProductLne] = []
    
        @property
        def total_ht(self) -> float:
            bla = 0.00
            for item in self.articles:
                bla += item.so_total_ht
        return bla
    
    
    item_line1 = ProductLne(prix=10.00,qtt_line=10)
    item_line2 = ProductLne(prix=12.00,qtt_line=10)
    
    print(item_line1.so_total_ht)
    print(item_line2.so_total_ht)
    
    bon1 = Bon()
    bon1.articles.append(item_line1)
    bon1.articles.append(item_line2)
    print(bon1.total_ht) #220
    

    【讨论】:

      猜你喜欢
      • 2021-04-04
      • 2021-12-01
      • 2021-08-14
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      相关资源
      最近更新 更多