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的记录),需先清理数据:
- 找出所有违反约束的记录(可在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) - 根据业务逻辑,手动合并或删除每个
work_performed下多余的未完成记录,确保每个work_performed最多仅存一条is_performed=False的记录。 - 重新执行迁移命令:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者Dante
相关产品推荐
相关产品推荐

