DeleteView marking inactive instead deleting?
Is there some elegant solution to using Django's DeleteView but instead actually deleting the objects, marking them inactive? I like the simplicity of the DeleteView but would want to keep the data at the backend, instead of removing it.
The DeleteView inherits DeletionMixin so you can just predefine the delete method. DeletionMixin
Override delete method in DeleteView as follows
class Example(DeleteView): def delete(self, request, *args, **kwargs): """ Calls the delete() method on the fetched object and then redirects to the success URL. """ self.object = self.get_object() self.object.is_deleted = True # Declare a boolean field is_deleted in your model. Default value is Flase. return HttpResponseRedirect(self.get_success_url())
Elegant solution would be overriding
Managerto update a field on
delete. This is an implementation as Abstract Model, so that it can be extended by any other Model. You can modify it as per your need, if you already have delete fields in your model.
Soft Deletion Abstract Model
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()
class SoftDeletionManager(models.Manager): def __init__(self, *args, **kwargs): self.alive_only = kwargs.pop('alive_only', True) super(SoftDeletionManager, self).__init__(*args, **kwargs) def get_queryset(self): if self.alive_only: return SoftDeletionQuerySet(self.model).filter(deleted_at=None) return SoftDeletionQuerySet(self.model) def hard_delete(self): return self.get_queryset().hard_delete()
class SoftDeletionQuerySet(QuerySet): def delete(self): return super(SoftDeletionQuerySet, self).update(deleted_at=timezone.now()) def hard_delete(self): return super(SoftDeletionQuerySet, self).delete() def alive(self): return self.filter(deleted_at=None) def dead(self): return self.exclude(deleted_at=None)
For explanation, see Soft Deletion in Django