Python Pydantic:基于其他字段在验证器中设置字段None';s值

Python Pydantic:基于其他字段在验证器中设置字段None';s值,python,pydantic,Python,Pydantic,我将pydanticBaseModel与以下验证器一起使用: 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 f

我将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'])
from datetime导入日期
输入导入列表,可选
从pydantic导入BaseModel、BaseConfig、validator
类模型(基本模型):
类配置(BaseConfig):
允许通过\u别名填充\u=真
字段={
“某些日期”:{
“别名”:“某些列表”
}
}
日期:可选[日期]
一些清单:清单[日期]
@验证器(“某个日期”,pre=True,always=True)
def验证_日期(cls,值):
如果len(value)<2:#这里的值是一些_列表
一无所获
返回值[0]#返回第一个值-假设它是一个日期字符串
#这再现了问题
m=型号(一些清单=['2019-01-03']
我想根据
some\u list
的值计算
some\u date
的值,如果满足某个条件,则将其设置为
None

My JSON从不包含字段
some_date
,它总是根据
some_list
填充,因此
pre=True,always=True
。但是,
some\u date
的默认验证器将在我的自定义验证器之后运行,如果
validate\u date
返回
None
,则该验证器将失败


是否有一种方法可以创建这样一个字段,该字段仅由另一个字段计算,并且仍然可以是可选的。

更新::正如其他人指出的,现在可以使用较新的版本(>=0.20)来完成。看见(旁注:即使OP的代码现在也可以工作,但是不使用别名就更好了。)


通过浏览pydantic的文档和源代码,我倾向于说pydantic的验证机制目前对验证函数中的类型转换(
list->date
list->NoneType
)的支持非常有限

但是,退一步说,您使用
别名
和标记
允许按别名填充似乎有点过载<如果len(some_list)>=2,则只需要使用code>some_date
作为
some_list[0]的快捷方式,否则无
,但它从未独立于
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]
类模型(基本模型):
一些列表:列表[日期]=。。。
@财产
定义某些日期(自我):
如果len(self.some_list)<2 else self.some_list[0]则返回None

您应该能够根据

您还可以将以下参数的任何子集添加到 签名(姓名必须匹配):

值:包含 任何先前验证的字段的名称到值映射

config: 模型配置

字段:正在验证的字段

**kwargs:如果提供,这将包括签名中未明确列出的上述参数

@validator()
def将_值_设置为_零(cls、v、值):
#在“值”中查找其他值,相应地设置v。

如果希望能够根据另一个字段动态修改一个字段,可以使用
value
参数。它保存前面的所有字段,并且要小心:顺序很重要。您可以使用
验证程序
根验证程序
执行此操作

使用
验证程序
>>自日期时间导入日期
>>>输入导入列表,可选
>>>从pydantic导入BaseModel,验证程序
>>>类模型(基本模型):
一些清单:清单[日期]
日期:可选[日期]
@验证程序(“某个日期”,始终=真)
def验证_日期(cls、值、值):
如果len(值[“某些列表])<2:
一无所获
返回值[“某些列表”][0]
>>>型号(部分清单=['2019-01-03','2020-01-03','2021-01-03']
模型(部分列表=[datetime.date(2019,1,3),datetime.date(2020,1,3),datetime.date(2021,1,3)],
some_date=datetime.date(2019,1,3))
但正如我所说,如果您交换
some\u list
some\u date
的顺序,您将有一个
键错误:“some\u list”

使用
root\u验证程序
另一种选择是使用
根验证程序
。这些措施适用于所有领域:

类模型(基本模型): 一些清单:清单[日期] 日期:可选[日期] @根校验器 def验证_日期(cls、值): 如果不是len(值[“某些列表])<2: 值[“某些日期”]=值[“某些列表”][0] 返回值 >>>型号(部分清单=['2019-01-03','2020-01-03','2021-01-03'] 模型(部分列表=[datetime.date(2019,1,3),datetime.date(2020,1,3),datetime.date(2021,1,3)], some_date=datetime.date(2019,1,3))
@normanius my bad,忘记了
allow…
字段
在一个内部配置类中。顺便说一句,我正在尝试使用python 3.6.1和pydantic 0.16.1 pydantic的较新版本(从0.20开始)更好地处理您的用例。我想知道我的方法是否可行,但您是对的,这个问题不应该这样解决