You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:10:29