使用django_get_or_create处理一对一关联字段时触发唯一约束错误
解决FactoryBoy中OneToOne关联的唯一约束错误
问题原因
你的UserFactory配置了django_get_or_create = ('username',),第二次调用UserFactory(username='foo')时会直接获取已存在的User实例,而非新建。但你定义的RelatedFactory(CustomerFactory...)会每次调用UserFactory时都执行——包括获取已有User的场景,这会尝试为同一个User创建第二个Customer实例,违反了Customer.user的OneToOneField唯一约束,触发IntegrityError。
解决方案
替换原来的RelatedFactory为post_generation钩子,仅在User实例新建且未关联Customer时创建对应的Customer:
修改UserFactory
import factory class UserFactory(factory.django.DjangoModelFactory): class Meta: model = User django_get_or_create = ('username',) first_name = factory.Faker("first_name", locale="fr_FR") last_name = factory.Faker("last_name", locale="fr_FR") username = factory.LazyAttribute(lambda m: f"{m.first_name[0]}{m.last_name[0]}".lower()) email = factory.LazyAttribute(lambda m: f"{m.first_name.lower()}.{m.last_name.lower()}@ielo.net") is_staff = False @factory.post_generation def customer(self, create, extracted, **kwargs): # 非创建模式(如build())直接返回 if not create: return # 仅当用户未关联Customer时才创建 if not hasattr(self, 'customer'): CustomerFactory(user=self, **kwargs)
保留CustomerFactory现有逻辑
class CustomerFactory(factory.django.DjangoModelFactory): class Meta: model = "customers.Customer" user = factory.SubFactory('myapp.tests.fixtures.UserFactory', customer=None)
效果说明
- 第一次调用
UserFactory(username='foo'):新建User,post_generation钩子检查到无关联Customer,自动创建对应实例。 - 第二次调用
UserFactory(username='foo'):获取已存在的User,钩子检测到已有Customer,跳过创建逻辑,不会触发唯一约束错误。
额外提示:如果需要自定义Customer字段,可通过UserFactory(customer__some_other_field="自定义值")的方式传递参数,钩子会将这些参数传给CustomerFactory。
内容的提问来源于stack exchange,提问作者Rémi Desgrange
相关产品推荐
相关产品推荐

