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

Django单元测试IntegrityError求助:重复键违反唯一约束

解决Django单元测试中的IntegrityError(重复主键约束)问题

根据你提供的代码和错误信息,问题出在OneToOne字段的重复关联上,错误提示里的development_developmentproject_project_id_key唯一约束冲突,说明同一个Project被多个DevelopmentProject(或关联模型)绑定了,而OneToOne关系要求一个Project只能对应一个关联对象。下面是具体的排查和解决步骤:

一、先定位核心问题

从错误信息和代码来看,最可能的两个根源:

  1. 模型定义存在笔误
  2. django-mommy自动创建了额外的关联对象,触发唯一约束

1. 修复模型定义的笔误

看你的Invoice模型代码:

job = models.ForeignKey(DevelopmentProject, related_name = 'job_invoices', blank = True, null = True, on_delete = models.CASCADE)

这里的DevelopmentProject是未在你提供的模型中定义的类,但你测试中创建的是Job模型并关联到Invoice。这很可能是笔误,应该把DevelopmentProject改为你实际的Job模型:

# 修正后(假设Job在development应用下)
job = models.ForeignKey('development.Job', related_name='job_invoices', blank=True, null=True, on_delete=models.CASCADE)

如果DevelopmentProject是你实际存在的模型,且它和Project是OneToOne关系,那你需要确保测试中不会重复创建它关联同一个Project。

2. 禁用django-mommy的自动关联创建

django-mommy默认会自动创建所有外键关联的对象,哪怕你已经手动指定了关联,这可能导致重复创建绑定同一个Project的对象,触发OneToOne约束。修改测试中创建Invoice的代码,禁用自动关联创建:

self.invoice = mommy.make(
    'development.invoice',
    job=self.job,
    Invoice_creator=self.userprofile,  # 可选:手动指定必填关联,避免自动创建
    _create_relatives=False  # 关键:禁用自动创建关联对象
)

3. 简化测试中的对象创建

你当前创建了2个Project,但只用到了第一个,多余的Project可能引发不必要的自动关联。可以改为只创建1个Project:

# 去掉_quantity=2,只创建1个Project
self.project = mommy.make('project_profile.Project', municipality=self.municipality[0])
self.job = mommy.make('development.Job', project=self.project)  # 无需索引[0]

4. 手动创建对象排查(终极方案)

如果以上方法都无效,放弃django-mommy,手动创建所有对象,彻底控制关联关系,排查冲突点:

def setUp(self):
    super().setUp()
    self.factory = RequestFactory()
    
    # 手动创建UserProfile(注意metropolitan是必填字段,必须赋值)
    self.userprofile = UserProfile.objects.create(metropolitan='Test Metro')
    
    # 手动创建Municipality
    self.municipality = Municipality.objects.create(name='Test City', abb='TC', userprofile=self.userprofile)
    
    # 手动创建Project
    self.project = Project.objects.create(name='Test Project', municipality=self.municipality)
    
    # 手动创建Job(OneToOne关联Project)
    self.job = Job.objects.create(project=self.project)
    
    # 手动创建Invoice
    self.invoice = Invoice.objects.create(PO='PO-001', invoice_type='Rental', job=self.job)
    
    # 测试URL
    the_url = reverse('development:update_invoice', args=(self.invoice.pk,))
    self.response = self.client.get(the_url, follow=True)

5. 检查数据库迁移和约束

确保你的迁移文件和模型定义一致,执行以下命令刷新数据库约束:

python manage.py makemigrations
python manage.py migrate

旧的迁移文件可能导致数据库约束和当前模型不匹配,引发奇怪的冲突。

内容的提问来源于stack exchange,提问作者EarlyCoder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:49:23