Django带条件UniqueConstraint触发IntegrityError异常问题排查
问题原因
你当前的UniqueConstraint规则逻辑不符合业务预期:
- 你设置的约束规则是:只要status为draft或live时,site、name、type三个字段的组合必须全局唯一。也就是说只要两条记录都满足status属于
[live, draft]的范围,不管它们的status值是否相同,只要site、name、type三个字段值一致,就会触发唯一约束冲突。你测试时创建的两条记录都命中了条件范围,三个核心字段完全一致,自然会抛出IntegrityError。 - 额外存在一个代码小问题:你的测试用例最后断言时使用了未定义的
config变量,修复约束后需要同步修正测试代码。
解决方案
- 调整模型的
UniqueConstraint规则,把status也加入唯一校验的字段列表:
from django.db.models import Q, UniqueConstraint class Configuration(models.Model): # 原有字段定义保持不变 class Meta(object): constraints = [ UniqueConstraint( fields=['site', 'name', 'type', 'status'], condition=(Q(status='draft') | Q(status='live')), name='unique_live_draft_config' ) ]
调整后规则变为:当status为draft或live时,site、name、type、status四个字段的组合必须唯一,这样就允许同一site、name、type下同时存在一个live版本和一个draft版本,但是不允许同时存在两个live或者两个draft版本,符合你的业务预期。
- 生成并执行新的迁移文件,让调整后的约束同步到数据库:
python manage.py makemigrations python manage.py migrate
- 修正测试用例中的变量名错误,把断言部分的变量改为实际定义的
config_live即可:
assert config_live.status == 'draft' assert str(config_live) == "Configuration: hello-world.org \"$cta-button-border\""
内容的提问来源于stack exchange,提问作者Esther Suh
相关产品推荐
相关产品推荐

