from django.db import models from django.utils import timezone class SoftDeleteQuerySet(models.QuerySet): def delete(self): return super().update(is_deleted=True, deleted_at=timezone.now()) def hard_delete(self): return super().delete() def alive(self): return self.filter(is_deleted=False) def dead(self): return self.filter(is_deleted=True) class SoftDeleteManager(models.Manager): def __init__(self, *args, **kwargs): self.alive_only = kwargs.pop('alive_only', None) super().__init__(*args, **kwargs) def get_queryset(self): if self.alive_only is True: return SoftDeleteQuerySet(self.model).filter(is_deleted=False) if self.alive_only is False: return SoftDeleteQuerySet(self.model).filter(is_deleted=True) if self.alive_only is None: return SoftDeleteQuerySet(self.model) def hard_delete(self): return self.get_queryset().hard_delete() class BaseModel(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) is_deleted = models.BooleanField(default=False) deleted_at = models.DateTimeField(null=True, blank=True) objects = SoftDeleteManager(alive_only=True) all_objects = SoftDeleteManager(alive_only=None) deleted_objects = SoftDeleteManager(alive_only=False) class Meta: abstract = True def delete(self, using=None, keep_parents=False): self.is_deleted = True self.deleted_at = timezone.now() self.save(using=using) def hard_delete(self, using=None, keep_parents=False): super().delete(using=using, keep_parents=keep_parents) def restore(self): self.is_deleted = False self.deleted_at = None self.save()