假设我有一堆表,其中对象被标记为已删除而不是实际删除。现在,我想强制执行一个约束,即只有一个具有特定字段值的非删除对象,但我可以有多个具有相同字段值的已删除对象。
class Deletable(models.Model):
deleted = models.BooleanField(default=False)
class Meta:
abstract=True
def soft_delete(self):
self.deleted=True
self.save()
class ConcreteModel(Deletable):
a = models.IntegerField()
b = models.IntegerField()
class Meta:
#wrong because there may have been some deleted rows
unique_together=('a', 'b')
强制执行约束的最佳方法是什么?
答案 0 :(得分:1)
在另一个字段中定义您的唯一约束:deleted
和您的伪唯一字段。然后,要表示软删除,请将模型的ID分配给deleted
;对于未删除的项目,请指定0。
使用这种方法,对于未删除的项目,由于deleted
字段具有一致性值,因此多字段唯一约束将有效地忽略deleted
的值并强制执行唯一性独特的领域;对于已删除的项目,deleted
将被考虑在内,并且由于它是唯一的,因此约束将始终令人满意 - 因此具有相同伪唯一字段值的任意数量的模型都可以共存。
例如,您可能正在寻找以下代码。
class Deletable(models.Model):
deleted = models.IntegerField(default=0)
class Meta:
abstract=True
def soft_delete(self):
self.deleted=self.id
self.save()
class ConcreteModel(Deletable):
a = models.IntegerField()
b = models.IntegerField()
class Meta:
unique_together=('a', 'b', 'deleted')
答案 1 :(得分:0)
答案 2 :(得分:0)
Django 2.2 以上的版本,可以使用 UniqueConstraint。
在您的模型上使用:
from django.db.models import Q
class ConcreteModel(Deletable):
a = models.IntegerField()
b = models.IntegerField()
class Meta:
constraints = [
models.UniqueConstraint(fields=['a', 'b'], condition=Q(deleted=False), name='a_b_unique')]