Pydantic 数据类句柄 ValidationError
Pydantic dataclass handle ValidationError
我正在寻找将数据传递到 pydantic 数据类时处理 ValidationError 的解决方案。
from pydantic import BaseModel
class TestB(BaseModel):
id: str
price : float
quantity : int
class TestA(BaseModel):
orderId: str
totalAmountPaid: float
products: List[TestB]
data_correct_type = {"orderId": "12341234", "totalAmountPaid": 395.5,
"products": [{"id": "abcd0001", "price": '299', "quantity": 1},
{"id": "abcd0002", "price": '199', "quantity": 1}]}
data_wrong_type = {"orderId": "12341234", "totalAmountPaid": 395.5,
"products": [{"id": "abcd0001", "price": '299', "quantity": 1},
{"id": "abcd0002", "price": 'abc', "quantity": 1}]}
result_pydantic_1 = TestA(**data_correct_type) #works
result_pydantic_2 = TestA(**data_wrong_type)
output:
raise 1 validation error for TestA
products -> 1 -> price
value is not a valid float (type=type_error.float)
有什么方法可以用 None 值之类的东西替换错误类型的字段?谢谢!
代码:
from pydantic import BaseModel, validator
from typing import Union
class P(BaseModel):
string: str
number: Union[float, None]
# pre=True → run before standard validators
@validator('number', pre=True)
def set_to_none_if_not_a_numeric(cls, v):
try:
return float(v)
except ValueError:
print('Not a number!')
return None
a = P(**{"string": "11", "number": "12aa"})
b = P(**{"string": "11", "number": "12"})
print(a)
print('----')
print(b)
输出:
Not a number!
string='11' number=None
----
string='11' number=12.0
回答
what if I want to do it with all the fields?
我建议首先检查pydantic
docs。很详细,有很多很好的例子
关于您的问题的示例:
class DemoModel(BaseModel):
square_numbers: List[int] = []
cube_numbers: List[int] = []
# '*' is the same as 'cube_numbers', 'square_numbers' here:
@validator('*', pre=True)
def split_str(cls, v):
if isinstance(v, str):
return v.split('|')
return v
@validator('cube_numbers', 'square_numbers')
def check_sum(cls, v):
if sum(v) > 42:
raise ValueError('sum of numbers greater than 42')
return v
所以你可以使用@validator('field1', 'field2')
或@validator('*')
回答
However what I want to achieve is for all the field in the dataclass, it will try to convert to the desired type as defined in the dataclass
发挥你的想象力:
代码:
from pydantic import BaseModel, validator
from typing import Optional
class P(BaseModel):
string_or_none: Optional[str]
float_or_none: Optional[float]
int_or_none: Optional[int]
bool_or_none: Optional[bool]
@validator('*', pre=True)
def cast_var_types(cls, value, field):
allowed_type = field.type_
try:
print(f'Try cast {value} to', str(allowed_type))
return allowed_type(value)
except ValueError:
return None
good_values = P(**{"string_or_none": 1234321, "float_or_none": "12.111", "int_or_none": "987", "bool_or_none": 1})
bad_values = P(**{"string_or_none": "this will be good anyway", "float_or_none": "abc", "int_or_none": "bac", "bool_or_none": "any value can be casted to bool"})
print()
print(' ====================================')
print()
for k in ["string_or_none", "float_or_none", "int_or_none", "bool_or_none"]:
print(k, "of good values is:")
print('type →', type(getattr(good_values, k)))
print('value →', getattr(good_values, k))
print('----------------')
print(k, "of bad values is:")
print('type →', type(getattr(bad_values, k)))
print('value →', getattr(bad_values, k))
print('----------------')
并输出:
Try cast 1234321 to <class 'str'>
Try cast 12.111 to <class 'float'>
Try cast 987 to <class 'int'>
Try cast 1 to <class 'bool'>
Try cast this will be good anyway to <class 'str'>
Try cast abc to <class 'float'>
Try cast bac to <class 'int'>
Try cast any value can be casted to bool to <class 'bool'>
====================================
string_or_none of good values is:
type → <class 'str'>
value → 1234321
----------------
string_or_none of bad values is:
type → <class 'str'>
value → this will be good anyway
----------------
float_or_none of good values is:
type → <class 'float'>
value → 12.111
----------------
float_or_none of bad values is:
type → <class 'NoneType'>
value → None
----------------
int_or_none of good values is:
type → <class 'int'>
value → 987
----------------
int_or_none of bad values is:
type → <class 'NoneType'>
value → None
----------------
bool_or_none of good values is:
type → <class 'bool'>
value → True
----------------
bool_or_none of bad values is:
type → <class 'bool'>
value → True
----------------
我正在寻找将数据传递到 pydantic 数据类时处理 ValidationError 的解决方案。
from pydantic import BaseModel
class TestB(BaseModel):
id: str
price : float
quantity : int
class TestA(BaseModel):
orderId: str
totalAmountPaid: float
products: List[TestB]
data_correct_type = {"orderId": "12341234", "totalAmountPaid": 395.5,
"products": [{"id": "abcd0001", "price": '299', "quantity": 1},
{"id": "abcd0002", "price": '199', "quantity": 1}]}
data_wrong_type = {"orderId": "12341234", "totalAmountPaid": 395.5,
"products": [{"id": "abcd0001", "price": '299', "quantity": 1},
{"id": "abcd0002", "price": 'abc', "quantity": 1}]}
result_pydantic_1 = TestA(**data_correct_type) #works
result_pydantic_2 = TestA(**data_wrong_type)
output:
raise 1 validation error for TestA
products -> 1 -> price
value is not a valid float (type=type_error.float)
有什么方法可以用 None 值之类的东西替换错误类型的字段?谢谢!
代码:
from pydantic import BaseModel, validator
from typing import Union
class P(BaseModel):
string: str
number: Union[float, None]
# pre=True → run before standard validators
@validator('number', pre=True)
def set_to_none_if_not_a_numeric(cls, v):
try:
return float(v)
except ValueError:
print('Not a number!')
return None
a = P(**{"string": "11", "number": "12aa"})
b = P(**{"string": "11", "number": "12"})
print(a)
print('----')
print(b)
输出:
Not a number!
string='11' number=None
----
string='11' number=12.0
回答
what if I want to do it with all the fields?
我建议首先检查pydantic
docs。很详细,有很多很好的例子
关于您的问题的示例:
class DemoModel(BaseModel):
square_numbers: List[int] = []
cube_numbers: List[int] = []
# '*' is the same as 'cube_numbers', 'square_numbers' here:
@validator('*', pre=True)
def split_str(cls, v):
if isinstance(v, str):
return v.split('|')
return v
@validator('cube_numbers', 'square_numbers')
def check_sum(cls, v):
if sum(v) > 42:
raise ValueError('sum of numbers greater than 42')
return v
所以你可以使用@validator('field1', 'field2')
或@validator('*')
回答
However what I want to achieve is for all the field in the dataclass, it will try to convert to the desired type as defined in the dataclass
发挥你的想象力:
代码:
from pydantic import BaseModel, validator
from typing import Optional
class P(BaseModel):
string_or_none: Optional[str]
float_or_none: Optional[float]
int_or_none: Optional[int]
bool_or_none: Optional[bool]
@validator('*', pre=True)
def cast_var_types(cls, value, field):
allowed_type = field.type_
try:
print(f'Try cast {value} to', str(allowed_type))
return allowed_type(value)
except ValueError:
return None
good_values = P(**{"string_or_none": 1234321, "float_or_none": "12.111", "int_or_none": "987", "bool_or_none": 1})
bad_values = P(**{"string_or_none": "this will be good anyway", "float_or_none": "abc", "int_or_none": "bac", "bool_or_none": "any value can be casted to bool"})
print()
print(' ====================================')
print()
for k in ["string_or_none", "float_or_none", "int_or_none", "bool_or_none"]:
print(k, "of good values is:")
print('type →', type(getattr(good_values, k)))
print('value →', getattr(good_values, k))
print('----------------')
print(k, "of bad values is:")
print('type →', type(getattr(bad_values, k)))
print('value →', getattr(bad_values, k))
print('----------------')
并输出:
Try cast 1234321 to <class 'str'>
Try cast 12.111 to <class 'float'>
Try cast 987 to <class 'int'>
Try cast 1 to <class 'bool'>
Try cast this will be good anyway to <class 'str'>
Try cast abc to <class 'float'>
Try cast bac to <class 'int'>
Try cast any value can be casted to bool to <class 'bool'>
====================================
string_or_none of good values is:
type → <class 'str'>
value → 1234321
----------------
string_or_none of bad values is:
type → <class 'str'>
value → this will be good anyway
----------------
float_or_none of good values is:
type → <class 'float'>
value → 12.111
----------------
float_or_none of bad values is:
type → <class 'NoneType'>
value → None
----------------
int_or_none of good values is:
type → <class 'int'>
value → 987
----------------
int_or_none of bad values is:
type → <class 'NoneType'>
value → None
----------------
bool_or_none of good values is:
type → <class 'bool'>
value → True
----------------
bool_or_none of bad values is:
type → <class 'bool'>
value → True
----------------