Soft Deletion in Django
--
Giving your users the ability to delete objects from your database is a risky proposition — some types of objects are low risk, but others, no matter how much you warn them of the risks of deleting things, will lead to customer requests. You know the kind — “So, I deleted this thing, but I didn’t mean to and now I really need it back…can you recover it?” Of course, databases don’t work that way. When a thing is deleted, it’s deleted.
So, the dream: be able to easily define some objects to be soft-deleted and others to be hard-deleted so that your developers don’t have to remember as they are interacting with objects which are which, and be able to easily recover deleted objects for your users when they need you to. Soft deletion can help with this.
The Model
Most objects in Django inherit from models.Model
. If we define a SoftDeletionModel
that our objects inherit from instead, we can give it whatever attributes we want, and trust that all models that inherit this way will have the same behavior, and we only have to remember it at the time we define the model, not every time we use it. It might look something like this:
class SoftDeletionModel(models.Model):
deleted_at = models.DateTimeField(blank=True, null=True)
objects = SoftDeletionManager()
all_objects = SoftDeletionManager(alive_only=False)
class Meta:
abstract = True
def delete(self):
self.deleted_at = timezone.now()
self.save()
def hard_delete(self):
super(SoftDeletionModel, self).delete()
The pieces:
deleted_at
: this means that all models inheriting from theSoftDeletionModel
will have this attribute available to be set. By default it will be null. I recommend a date instead of a boolean so that you can create a background job that hard-deletes any objects that were “deleted” more than 24 hours/7 days/30 days (whatever the right cadence is for you and your users ) ago — data that users choose to delete should actually be deleted.- We’ll look at
objects
andall_objects
in the next section. This is what makes this so powerful abstract = True
: This just means we won’t ever define aSoftDeletionModel
object on its own. More detail from the Django docs here.- The
delete
method means that whenever you call.delete()
on any object that inherits from theSoftDeletionModel
, it won’t actually be deleted from the database — its…