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

Django模型约束问题:同一work_performed仅允许一条is_performed=False记录

解决Django模型中按外键限制布尔字段唯一的问题

正确的约束配置

要实现「针对指定work_performed仅允许一条is_performed=False记录」的需求,需调整UniqueConstraint的配置逻辑,仅将work_performed作为唯一约束字段,结合条件限定is_performed=False:

class MaintenancePersonnel(models.Model):
    performed_by = models.ForeignKey(User, on_delete=models.CASCADE)
    work_performed = models.ForeignKey(EquipmentMaintenanceSchedule, on_delete=models.CASCADE)
    comments = models.TextField(blank=True, null=True)
    is_performed = models.BooleanField(default=False)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['work_performed'],
                condition=models.Q(is_performed=False),
                name='unique_unperformed_per_work'
            )
        ]

原配置问题分析

你之前的约束错误地将is_performed加入了fields列表,结合condition=models.Q(is_performed=False)后,实际约束逻辑变成:全局所有is_performed=False的记录,(work_performed, False)的组合必须唯一。由于is_performed固定为False,这等同于要求所有未完成记录的work_performed不能重复,完全偏离了「按work_performed分别限制」的需求。

迁移报错解决

迁移时提示Key (is_performed)=(f)重复,是因为当前数据库已存在违反新约束的数据(比如同一个work_performed下有多条is_performed=False的记录),需先清理数据:

  1. 找出所有违反约束的记录(可在Django Shell中执行):
    from django.db.models import Count
    duplicates = MaintenancePersonnel.objects.filter(is_performed=False).values('work_performed').annotate(count=Count('id')).filter(count__gt=1)
    
  2. 根据业务逻辑,手动合并或删除每个work_performed下多余的未完成记录,确保每个work_performed最多仅存一条is_performed=False的记录。
  3. 重新执行迁移命令:
    python manage.py makemigrations
    python manage.py migrate
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:21:53