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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:32:30