代码之家  ›  专栏  ›  技术社区  ›  Dániel Nagy

pydantic:根据其他字段的值在验证器中设置字段none

  •  1
  • Dániel Nagy  · 技术社区  · 6 年前

    我用的是Pydantic BaseModel 使用这样的验证器:

    from datetime import date
    from typing import List, Optional
    from pydantic import BaseModel, BaseConfig, validator
    
    class Model(BaseModel):
        class Config(BaseConfig):
            allow_population_by_alias = True
            fields = {
                "some_date": {
                    "alias": "some_list"
                }
            }
        some_date: Optional[date]
        some_list: List[date]
    
        @validator("some_date", pre=True, always=True)
        def validate_date(cls, value):
            if len(value) < 2: # here value is some_list
                return None
            return value[0] # return the first value - let's assume it's a date string
    
    # This reproduces the problem
    m = Model(some_list=['2019-01-03'])
    

    我想计算 some_date 基于 some_list 并使之成为 None 如果满足某个条件。

    我的json从不包含字段 某日 ,它总是基于 一些名单 因此 pre=True, always=True . 但是,的默认验证器 某日 将运行 之后 我的定制,如果 validate_date 收益率 没有 .

    有没有一种方法可以创建这样一个字段,该字段只能由另一个字段计算,并且仍然可以 Optional ?

    1 回复  |  直到 6 年前
        1
  •  1
  •   normanius    6 年前

    我倾向于说这在你的尝试中是不可能的。

    您正确地指出了 date 被称为 之后 习俗 validate_date 从您的数据模型。可以找到相关的源代码 here: pydantic.fields.py (截至2019年1月,Git Hash:19320BF)。显然, allow_none -验证程序的级联不支持模式,请参阅 pydantic.Field._apply_validators 详情。更具体地说,从未测试过特定验证器的输出 None ,该测试在上游进行 Model.validate .

    从skim阅读文档和pydantic的来源来看,我倾向于说pydantic的验证机制目前对类型转换的支持非常有限。( list -> date , list -> NoneType )在验证函数中。如果您的用例有很好的参数,那么您可能希望请求该特性。 here .

    但是,后退一步,使用 alias 旗帜 allow_population_by_alias (无论如何,这是不推荐的,如 documentation )好像有点超载。 some_date 只需要作为 some_list[0] if len(some_list) >= 2 else None 但是它从来没有独立于 some_list . 如果真是这样的话,为什么不选择下面简单得多的选项呢?

    class Model(BaseModel):
        some_list: List[date] = ...
    
        @property 
        def some_date(self):
            return None if len(self.some_list) < 2 else self.some_list[0]