如何在Factory Boy的SubFactory中动态选择工厂类
如何在Factory Boy的SubFactory中动态选择工厂类
嘿,这个需求我之前做项目的时候刚好碰到过,Factory Boy其实提供了几种实用的方式来实现动态选择SubFactory的工厂类,最适配你这个布尔参数场景的就是用factory.Maybe,写法简洁又直观!
先给你看适配你需求的完整代码示例:
# 假设你已经导入了对应的用户工厂类 BASIC_USER_FACTORY = BasicUserFactory ADMIN_USER_FACTORY = AdminUserFactory class ProjectWithOwnerFactory(DjangoModelFactory): class Meta: model = Project # 记得替换成你的实际Project模型 class Params: admin_owner = False name = factory.Faker('company') date_created = factory.Faker('date_this_year') # 根据admin_owner参数动态切换子工厂 owner = factory.Maybe( 'admin_owner', yes_declaration=factory.SubFactory(ADMIN_USER_FACTORY), no_declaration=factory.SubFactory(BASIC_USER_FACTORY), )
这样写之后,完全符合你的调用预期:
ProjectWithOwnerFactory():默认admin_owner=False,会用BASIC_USER_FACTORY创建普通用户作为项目所有者ProjectWithOwnerFactory(admin_owner=True):触发yes_declaration,用ADMIN_USER_FACTORY创建管理员用户
如果你后续需要更复杂的判断逻辑(比如参数不是布尔值,而是多角色的字符串),可以用factory.LazyAttribute来实现,通过字典映射灵活选择工厂:
class ProjectWithOwnerFactory(DjangoModelFactory): class Meta: model = Project class Params: owner_role = 'basic' # 支持'basic'/'admin'等多角色 name = factory.Faker('company') date_created = factory.Faker('date_this_year') owner = factory.LazyAttribute(lambda self: { 'basic': BASIC_USER_FACTORY, 'admin': ADMIN_USER_FACTORY }[self.owner_role]())
这种方式还能方便给子工厂传递额外参数,比如需要关联当前项目的话,可以写成BASIC_USER_FACTORY(project=self)。
你之前尝试SelfAttribute和LazyAttribute失败,大概率是因为直接把它们传给了SubFactory的第一个参数——SubFactory期望的是工厂类或者字符串路径,而SelfAttribute返回的是模型实例的属性值,不是工厂类,所以才会报错。上面的两种方法都是直接在字段层面动态生成对应的子工厂实例,完美避开了这个问题。
备注:内容来源于stack exchange,提问作者ddrddrr
相关产品推荐
相关产品推荐

