Say I have a bunch of tables where the objects are marked deleted rather than actually deleted. Now, I want to enforce a constraint that there can be only one non-deleted object with a particular set of field values, but I can have multiple deleted objects with the same field values.
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')
What is the best way to enforce the constraint?
Define your unique constraint across one more field:
deletedand your pseudo-unique fields. Then, to represent a soft delete, assign the model’s id todeleted; for undeleted items, assign 0.With this approach, for undeleted items, since the
deletedfield is consistently-valued, the multi-field unique constraint will effectively ignore the value of thedeletedand enforce uniqueness for just the pseudo-unique fields; for deleted items,deletedwill be taken into account, and since it is unique, the constraint will always be satisified – so any number of models with the same pseudo-unique fields’ values can coexist.For example, the following code might be what you’re looking for.