Django:更复杂的唯一性约束?

2 投票
2 回答
1298 浏览
提问于 2025-04-17 01:39

在我的模型中:

class MyModel(models.Model):
  active = models.BooleanField()
  path = models.CharField(max_length = 512)

我想要确保当“active”属性为真时,“path”属性在所有实例中是唯一的。

看起来重写save()方法可能不太管用,因为如果同时进行两个保存操作,它们都有可能通过检查,然后都继续保存。有没有什么技巧或者自定义的SQL(我在用MySQL)可以在数据库层面实现这样的条件唯一性约束呢?

2 个回答

1

我在找其他东西的时候偶然发现了这个,不过对于任何其他来到这里的人来说,这在Django 2.2及以上版本中非常简单(这个版本是在这个问题被问出很久之后发布的),这要归功于UniqueConstraint

from django.db.models import Q, UniqueConstraint

class MyModel(models.Model):

    active = models.BooleanField()

    path = models.CharField(max_length=512)

    class Meta:
        constraints = [UniqueConstraint(fields=["path"], condition=Q(active=True)]
2

你可能在寻找的是模型验证。这是在1.2版本中引入的,并且有很好的文档说明。你可以查看这个链接了解更多信息:Django模型实例:验证对象

虽然你可以写一些复杂的SQL来实现这个功能,但只要数据库的记录都是通过Django的ORM(对象关系映射)创建的,那么使用模型验证会更容易维护。

顺便说一下,我对你如何在数据库层面上做到这一点很感兴趣,除了使用某种预提交触发器。一个值的唯一性依赖于另一个值为真的情况,我还没有见过类似的模式。如果在active和path上有一个两字段的唯一约束,那么对于给定的path值,可以有1个为假、1个为真,以及任意数量的NULL active行(假设active是可以为空的,比如NullBooleanField可以提供这样的功能)。

撰写回答