使用Factory Boy构建Django关联模型时报递归深度超限错误如何解决
报错原因
你遇到的递归错误是双向自动创建关联对象形成了无限循环导致的,循环链路如下:
- 调用
UserFactory()创建用户时,你定义的RelatedFactory会自动创建绑定当前用户的Employee实例 - 创建
Employee实例时,user和creator两个字段都声明了SubFactory(UserFactory),会再次触发新的User实例创建 - 新创建的User又会触发
RelatedFactory创建新的Employee,无限重复直到栈溢出。
推荐解决方案
取消双向自动绑定逻辑,改为主动控制关联对象的创建,同时复用关联字段避免重复生成用户:
- 移除UserFactory中自动创建Employee的
RelatedFactory,改用post_generation参数按需生成关联的Employee - EmployeeFactory的
creator字段默认复用自身绑定的user,避免额外创建新用户
修改后的代码如下:
class UserFactory(factory.django.DjangoModelFactory): class Meta: model = User first_name = fake.first_name() last_name = fake.last_name() username = factory.Sequence(lambda n: "user_%d" % n) email = fake.ascii_email() # 可选参数,主动传入True时才会生成关联的Employee @factory.post_generation def with_employee(self, create, extracted, **kwargs): if not create or not extracted: return EmployeeFactory(user=self, creator=self, **kwargs) class EmployeeFactory(factory.django.DjangoModelFactory): class Meta: model = Employee first_name = fake.first_name() last_name = fake.last_name() phone = "+88005553535" email = fake.ascii_email() user = factory.SubFactory(UserFactory) # 复用当前Employee关联的user作为creator,避免额外创建新User creator = factory.SelfAttribute('user')
使用方式:
- 仅创建无关联Employee的用户:
user = UserFactory() - 创建用户同时生成关联的Employee:
user = UserFactory(with_employee=True) - 单独创建Employee:
employee = EmployeeFactory(),自动生成关联用户,creator默认和关联用户一致 - 自定义creator:
other_user = UserFactory(); employee = EmployeeFactory(creator=other_user)
备选方案(保留User自动创建Employee的逻辑)
如果需要保留UserFactory默认自动生成关联Employee的逻辑,可以通过参数控制打断循环:
class UserFactory(factory.django.DjangoModelFactory): class Meta: model = User exclude = ('create_employee',) # 控制是否自动创建关联Employee,不写入数据库 create_employee = True first_name = fake.first_name() last_name = fake.last_name() username = factory.Sequence(lambda n: "user_%d" % n) email = fake.ascii_email() employee = factory.RelatedFactory( "control_room.tests.factories.EmployeeFactory", factory_related_name='user' ) class EmployeeFactory(factory.django.DjangoModelFactory): class Meta: model = Employee first_name = fake.first_name() last_name = fake.last_name() phone = "+88005553535" email = fake.ascii_email() # 创建关联user时关闭自动生成Employee的逻辑,打断循环 user = factory.SubFactory(UserFactory, create_employee=False) creator = factory.SubFactory(UserFactory)
内容的提问来源于stack exchange,提问作者Labtoxs
相关产品推荐
相关产品推荐

