Factory_boy中Trait内使用RelatedFactory无法创建关联对象问题求解
错误根源
- 命名冲突:你在PurchaseFactory顶层定义了名为
info的RelatedFactory,同时在Params里又定义了同名的infoTrait,二者冲突,传info=True时会优先作为参数标志位处理,覆盖了原本的RelatedFactory逻辑。 - PurchaseInfoFactory配置错误:Meta类的model属性写为了
PurchaseInfoField,应对应实际模型类PurchaseInfo。 - Trait内不能通过自定义属性名绑定RelatedFactory:RelatedFactory必须作为工厂类的直接属性才能触发关联对象创建,放在Trait的自定义属性下不会生效。
- 你的当前配置默认就会生成全空的PurchaseInfo,不符合按需创建的诉求。
正确实现方案(推荐用post_generation钩子,灵活性更高)
import factory from factory.django import DjangoModelFactory from factory import SubFactory from django.utils import timezone from dateutil.relativedelta import relativedelta # 修正PurchaseInfoFactory的模型指向 class PurchaseInfoFactory(DjangoModelFactory): class Meta: model = PurchaseInfo lock = None lock_by = None class PurchaseFactory(DjangoModelFactory): class Meta: model = Purchase class Params: # 声明控制开关,不和实际关联字段重名 with_info = False with_locked_info = False # 用post_generation钩子控制关联对象创建逻辑 @factory.post_generation def info(self, create, extracted, **kwargs): if not create: return # build模式下不创建关联对象 # 支持直接传入自定义PurchaseInfo属性 if extracted: PurchaseInfo.objects.create(purchase=self, **(extracted | kwargs)) return # 处理标志位触发的场景 if self.with_info: PurchaseInfoFactory(purchase=self, **kwargs) if self.with_locked_info: PurchaseInfoFactory( purchase=self, lock=timezone.now() - relativedelta(months=1), lock_by=SubFactory(UserFactory, user_id=1), **kwargs )
使用说明
- 默认调用
p = PurchaseFactory():不会生成任何PurchaseInfo对象 - 调用
p = PurchaseFactory(with_info=True):生成字段全为null的PurchaseInfo对象 - 调用
p = PurchaseFactory(with_locked_info=True):生成带指定lock、lock_by值的PurchaseInfo对象 - 如需默认就生成全空的PurchaseInfo,只需把Params里的
with_info默认值改为True即可
内容的提问来源于stack exchange,提问作者mj_
相关产品推荐
相关产品推荐

