Python Pydantic:基于其他字段在验证器中设置字段None';s值
我将pydanticPython 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
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开始)更好地处理您的用例。我想知道我的方法是否可行,但您是对的,这个问题不应该这样解决