python - Pydantic:根据其他字段的值在验证器中设置字段 None
问题描述
我将 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
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 从不包含该字段some_date
,它始终基于some_list
因此填充pre=True, always=True
。但是,默认验证器some_date
将在validate_date
我的自定义验证器之后运行,如果返回,它将失败None
。
有没有办法创建这样一个只能由另一个计算并且仍然可以的字段Optional
?
解决方案
如果您希望能够根据另一个字段动态修改一个字段,您可以使用values
参数。它包含所有先前的字段,并且小心:顺序很重要。您可以使用 avalidator
或 a来执行此操作root_validator
。
带一个validator
>>> from datetime import date
>>> from typing import List, Optional
>>> from pydantic import BaseModel, validator
>>> class Model(BaseModel):
some_list: List[date]
some_date: Optional[date]
@validator("some_date", always=True)
def validate_date(cls, value, values):
if len(values["some_list"]) < 2:
return None
return values["some_list"][0]
>>> Model(some_list=['2019-01-03', '2020-01-03', '2021-01-03'])
Model(some_list=[datetime.date(2019, 1, 3), datetime.date(2020, 1, 3), datetime.date(2021, 1, 3)],
some_date=datetime.date(2019, 1, 3))
some_list
但是正如我所说,如果您交换and的顺序some_date
,您将有一个KeyError: 'some_list'
!
带一个root_validator
另一种选择是使用root_validator
. 这些作用于所有领域:
>>> class Model(BaseModel):
some_list: List[date]
some_date: Optional[date]
@root_validator
def validate_date(cls, values):
if not len(values["some_list"]) < 2:
values["some_date"] = values["some_list"][0]
return values
>>> Model(some_list=['2019-01-03', '2020-01-03', '2021-01-03'])
Model(some_list=[datetime.date(2019, 1, 3), datetime.date(2020, 1, 3), datetime.date(2021, 1, 3)],
some_date=datetime.date(2019, 1, 3))
推荐阅读
- java - 为什么在java中最后一个索引的子字符串不等于“”?
- css - :not 选择器,为正文中的所有内容设置样式,除了
- python - 通过对值求和来遍历字典键
- xamarin - 我需要创建一个垂直列表视图。在 Xamarin.Forms 上
- lua - lua为什么有时在lua中乘法和除法的精度不一样?例如下面
- java - 如何在 CompletableFuture 中抛出检查异常?
- javascript - 如何在单击 javascript/jquery 中的文本时滚动到底部?
- python - Python2.7 json加载文本列表回一个int列表
- javascript - 如何在不重新加载页面的情况下获取 PHP 文件中的 javascript 数据
- sql - 消息 402,级别 16,状态 1,第 4 行数据类型 varchar 和 varchar 在减法运算符中不兼容