如何让pydantic-factories生成满足Pydantic验证条件的模拟数据?
解决Pydantic ModelFactory生成符合验证规则模拟数据的方案
针对日期验证场景的直接解决方法
重写ModelFactory中关联字段的生成逻辑,确保end_date基于已生成的start_date生成,自然满足"晚于"的要求:
from datetime import datetime, timedelta from pydantic import BaseModel, validator from pydantic_factories import ModelFactory import random class Dates(BaseModel): start_date: datetime end_date: datetime @validator("end_date") def end_after_start(cls, v, values): if "start_date" in values and v <= values["start_date"]: raise ValueError("end_date must be after start_date") return v class DatesFactory(ModelFactory): __model__ = Dates @classmethod def end_date(cls) -> datetime: # 先获取已生成的start_date值 start_date = cls.get_field_value("start_date") # 生成比start_date晚1-30天的随机日期 return start_date + timedelta(days=random.randint(1, 30)) # 测试生成 valid_dates = DatesFactory.build() print(valid_dates.start_date < valid_dates.end_date) # 输出True
复杂验证场景的通用方案
当模型存在多字段联动、条件判断等复杂验证规则时,可采用以下几种通用思路:
1. 重写Factory的build方法
先生成基础随机数据,再根据验证规则调整数据后再实例化模型:
class ComplexModel(BaseModel): value_a: int value_b: int status: str @validator("status") def set_status_based_on_values(cls, v, values): if "value_a" in values and "value_b" in values: if values["value_a"] > values["value_b"]: return "a_gt_b" return "b_gt_a" return v class ComplexModelFactory(ModelFactory): __model__ = ComplexModel @classmethod def build(cls, **kwargs): # 生成初始随机数据 raw_data = super().build(**kwargs) # 按照验证规则调整字段 if raw_data["value_a"] > raw_data["value_b"]: raw_data["status"] = "a_gt_b" else: raw_data["status"] = "b_gt_a" # 用调整后的数据实例化模型 return cls.__model__(**raw_data)
2. 使用post_generation钩子
利用pydantic_factories提供的post_generation装饰器,在实例生成后直接修正字段值:
from pydantic_factories import post_generation class DatesFactory(ModelFactory): __model__ = Dates @post_generation def adjust_dates(cls, instance, create, **kwargs): # 检查并修正end_date if instance.end_date <= instance.start_date: instance.end_date = instance.start_date + timedelta(days=random.randint(1, 30)) return instance
3. 自定义字段生成器
为有复杂依赖的字段编写专属生成函数,直接关联依赖字段的生成结果:
def generate_valid_status(value_a: int, value_b: int) -> str: return "a_gt_b" if value_a > value_b else "b_gt_a" class ComplexModelFactory(ModelFactory): __model__ = ComplexModel @classmethod def status(cls) -> str: value_a = cls.get_field_value("value_a") value_b = cls.get_field_value("value_b") return generate_valid_status(value_a, value_b)
4. 特殊场景:绕过验证(不推荐)
如果仅需要生成结构正确但无需验证的数据,可使用Pydantic的model_construct方法跳过验证,但会失去数据合法性保障:
class DatesFactory(ModelFactory): __model__ = Dates @classmethod def build(cls, **kwargs): raw_data = super().build(**kwargs) # 跳过验证直接构建实例 return cls.__model__.model_construct(**raw_data)
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

