问题描述
我正在尝试创建 timedelta 的子类,该子类期望接收毫秒而不是秒,但目前无法正常工作。
我是不是违背了原则?使用 Pydantic 是否有“正确”的方法来实现这一目标?或者我是否需要告诉 Pydantic Millisecondtimedelta
只是一个 timedelta
..
from datetime import timedelta from pydantic import BaseModel class Millisecondtimedelta(timedelta): @classmethod def __get_validators__(cls): # timedelta expects seconds yield lambda v: v / 1000 yield cls class MyModel(BaseModel): td: Millisecondtimedelta data = { "td": 7598040,} print(MyModel(**data))
@H_404_11@结果:
Traceback (most recent call last): File "main.py",line 14,in <module> class MyModel(BaseModel): File "pydantic/main.py",line 262,in pydantic.main.ModelMetaclass.__new__ File "pydantic/fields.py",line 315,in pydantic.fields.ModelField.infer File "pydantic/fields.py",line 284,in pydantic.fields.ModelField.__init__ File "pydantic/fields.py",line 362,in pydantic.fields.ModelField.prepare File "pydantic/fields.py",line 541,in pydantic.fields.ModelField.populate_validators File "pydantic/class_validators.py",line 255,in pydantic.class_validators.prep_validators File "pydantic/class_validators.py",line 238,in pydantic.class_validators.make_generic_validator File "/usr/lib/python3.8/inspect.py",line 3105,in signature return Signature.from_callable(obj,follow_wrapped=follow_wrapped) File "/usr/lib/python3.8/inspect.py",line 2854,in from_callable return _signature_from_callable(obj,sigcls=cls,File "/usr/lib/python3.8/inspect.py",line 2384,in _signature_from_callable raise ValueError( ValueError: no signature found for builtin type <class '__main__.Millisecondtimedelta'>
@H_404_11@解决方法
如 on the doc page of
__get_validators__()
所示,您需要产生一个或多个验证器。修改后的类报告如下;问题是 Pydantic 理解(对于 timedelta 字段)int 并浮动为秒 (source)。
class MillisecondTimedelta(timedelta): @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls,v): if any(isinstance(v,t) for t in (int,float)): return cls(milliseconds=v)
现在一切正常。
>>> data = {"td": 1000} >>> print(MyModel(**data)) td=MillisecondTimedelta(seconds=1)
编辑:没有自定义类和验证器,可以使用函数来编辑要分配给类构造函数的值;需要装饰这个函数,as seen here
class MyModel(BaseModel): td: timedelta @validator('td') def convert_to_ms(cls,v): return v / 1000
此解决方案也有效:
,>>> data = {"td": 3000} >>> print(MyModel(**data)) td=datetime.timedelta(seconds=3)
啊哈,原来我需要改变两件事。
实际上从验证器返回一个
timedelta
,我返回的是cls
,它是我的自定义子类。不要继承
timedelta
from datetime import timedelta from pydantic import BaseModel class MillisecondTimedelta: @classmethod def __get_validators__(cls): yield lambda v: timedelta(milliseconds=v) class MyModel(BaseModel): td: MillisecondTimedelta data = { "td": 7598040,} print(repr(MyModel(**data)))
MyModel(td=datetime.timedelta(seconds=7598,microseconds=40000))