2

假设我有一堆表,其中对象被标记为已删除而不是实际删除。现在,我想强制执行一个约束,即只能有一个具有一组特定字段值的未删除对象,但我可以有多个具有相同字段值的已删除对象。

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')

执行约束的最佳方法是什么?

4

3 回答 3

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')
于 2012-06-12T23:44:10.567 回答
1

对于高于 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')]
于 2021-05-25T07:36:53.550 回答
0

使用模型验证。

https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects

于 2012-06-12T23:31:30.977 回答