如何在Pydantic中通过condecimal实现Decimal|None字段类型?
问题解决:Pydantic模型字段限制小数位数且转为float类型
你遇到的问题核心在于:
condecimal本质是约束Decimal类型,所以直接用它会导致字段类型为Decimal | None而非float | Nonefloat类型不支持decimal_places约束,因为浮点数无法精确控制十进制小数位数,Pydantic因此报错提示该约束未被强制执行
可行解决方案
方案1:用字段验证器转换Decimal为float
通过condecimal定义约束,再用field_validator将验证后的Decimal值转为float,同时修正类型提示:
from pydantic import BaseModel, condecimal, Field, field_validator from typing import Optional from decimal import Decimal class Example(BaseModel): some_field: Optional[float] = Field(alias="Some alias") @field_validator('some_field', mode='before') def validate_and_convert(cls, v): # 先用condecimal的规则验证值 validated_decimal = condecimal(ge=0.01, decimal_places=2)(v) # 转换为float return float(validated_decimal)
方案2:用Annotated组合约束与转换
通过Annotated将约束、转换逻辑封装,让字段类型直接显示为float | None:
from pydantic import BaseModel, condecimal, AfterValidator, PlainSerializer from typing import Optional, Annotated from decimal import Decimal # 定义带约束的转换类型 ConstrainedPositiveFloat = Annotated[ Decimal, condecimal(ge=0.01, decimal_places=2), AfterValidator(lambda x: float(x)), # 验证后转float PlainSerializer(lambda x: float(x), return_type=float) # 序列化时保持float类型 ] class Example(BaseModel): some_field: Optional[ConstrainedPositiveFloat] = Field(alias="Some alias")
补充说明
- Decimal类型比float更适合处理精确的小数计算,如果业务允许,建议直接使用
Optional[condecimal(...)]作为字段类型,无需转换为float - 若必须用float,上述两种方案都能保证输入值符合正数、两位小数的约束,同时输出float类型
内容的提问来源于stack exchange,提问作者Martiono
相关产品推荐
相关产品推荐

