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.

3 answers

  • answered 2018-10-11 20:07 Kristiyan Gospodinov

    The DeleteView inherits DeletionMixin so you can just predefine the delete method. DeletionMixin

  • answered 2018-10-12 03:59 a_k_v

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

  • answered 2018-10-12 04:59 Dhirendra

    Elegant solution would be overriding Model & Manager to 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()
    

    Object Manager

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

    QuerySet

    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