特定字段为True时的Django唯一性约束

时间:2015-08-20 17:04:25

标签: django

我有一个像这样的Django模型:

class Process(Place):
    isRunning = models.BooleanField(default=True)
    name      = models.CharField(max_length=20)

我希望在name为真时强制isRunning字段是唯一的。

Django模型中是否可以使用此约束?

<小时/> 这可能是this question的副本,但它没有得到接受的答案,并且Django自被问及以来已经发展了很多。

3 个答案:

答案 0 :(得分:2)

如果您的数据库支持它,您可以设置partial unique index

  

部分索引是在表的子集上构建的索引;子集由条件表达式(称为部分索引的谓词)定义。索引仅包含满足谓词的表行的条目。

2.2版以下没有特殊的Django支持,但您可以在数据迁移中进行设置(有关详细信息,请参阅here)。

在你的情况下,它看起来像:

operations = [
    migrations.RunSQL("CREATE UNIQUE INDEX running_name ON app_process(isRunning, name)
                       WHERE isRunning"),
]

从版本2.2开始,您只需在模型中declare the partial unique index

from django.db.models import Q, UniqueConstraint

class Process(Place):
    ...
    class Meta:
        constraints = [UniqueConstraint(fields=["name"], condition=Q(isRunning=True))]

答案 1 :(得分:1)

唯一字段表示在该字段的数据库中构建唯一索引。

现在,由于您的字段依赖于同一模型中的字段,因此您可以选择在保存模型时对其进行验证。

您可以覆盖模型save()方法,如:

def save(self, *args, **kwargs):
    #check if isRunning is true or not    
    super(Model, self).save(*args, **kwargs)

答案 2 :(得分:0)

您可以添加一个额外的字段,例如stopped_at,以记录进程被终止的时间。

并创建一个独特的约束:

unique_together = ('name', 'stopped_at')

对于新进程,stopped_at可以设置为None或某个常量值。

此约束将确保名称在正在运行的进程中是唯一的。并且已停止的进程可能具有相同的名称,因为它们的stopped_at总是不同(希望或者您可以向此棘手的字段添加其他信息以保证已停止进程的唯一性)。