26
loading...
This website collects cookies to deliver better user experience
class SoftDeleteModel(models.Model):
is_deleted = models.BooleanField(default=False)
def soft_delete(self):
self.is_deleted = True
self.save()
def restore(self):
self.is_deleted = False
self.save()
class Meta:
abstract = True
abstract = True
. This means that Django will not create a database table for it.SoftDeleteModel
to grant them the ability to be soft-deleted. Let's take the example of a Note
model.class Note(SoftDeleteModel):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="notes")
title = models.CharField(max_length=32)
content = models.CharField(max_length=255)
is_deleted
in order to exclude records that have been soft-deleted.Note.objects.filter(is_deleted=False)
python manage.py shell
in your terminal.from django.contrib.auth.models import User
from tutorialapp.models import Note
User
object:john = User.objects.create_user('john', '[email protected]', 'johnpassword')
my_note = Note.objects.create(user=john, title="Strawberry Fields", content="Strawberry Fields Forever")
another_note = Note.objects.create(user=john, title="Here Comes The Sun", content="It's All Right")
my_note.soft_delete()
my_note.restore()
Note.objects.all()
Note.objects.filter(is_deleted=False)
is_deleted=False
each time we write a query.MyModel.objects.all()
. The .objects
part in the statement is the manager. Managers act as the 'bridge' between your Django code and the database. They control the database operations performed on the tables that they 'manage'.class SoftDeleteManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_deleted=False)
SoftDeleteModel
base class:class SoftDeleteModel(models.Model):
is_deleted = models.BooleanField(default=False)
objects = models.Manager()
undeleted_objects = SoftDeleteManager()
def soft_delete(self):
self.is_deleted = True
self.save()
def restore(self):
self.is_deleted = False
self.save()
class Meta:
abstract = True
objects
manager as well.Note.undeleted_objects.all()
QuerySet
of undeleted notes.Note.objects.all()
Note.objects.filter(user=john, is_deleted=False)
john.notes.all()
QuerySet
contains records that we had soft deleted. This is because Django is using the default objects
manager to perform the reverse lookup, which, as you may recall, does not filter out soft deleted records.SoftDeleteManager
to perform reverse lookups? We can simply replace the default objects
manager in our SoftDeleteModel
:class SoftDeleteModel(models.Model):
is_deleted = models.BooleanField(default=False)
objects = SoftDeleteManager()
all_objects = models.Manager()
def soft_delete(self):
self.is_deleted = True
self.save()
def restore(self):
self.is_deleted = False
self.save()
class Meta:
abstract = True
objects
manager will automatically filter out soft-deleted objects when querying our database, ensuring they never leak into our application under any circumstances! If we want to, we can still include soft deleted objects in our queries by making use of the all_objects
manager.Note.all_objects.all()
deleted_at
to our SoftDeleteModel
:deleted_at = models.DateTimeField(null=True, default=None)
soft_delete
and restore
methods as follows:def soft_delete(self):
self.deleted_at = timezone.now()
self.save()
def restore(self):
self.deleted_at = None
self.save()
deleted_at
will be null, while for soft deleted records, it will contain the date and time at which it was deleted.deleted_at
attribute makes our previously created is_deleted
attribute redundant, because we can simply perform a null-check on deleted_at
to find out whether the record is soft deleted or not.SoftDeleteModel
now looks like this:class SoftDeleteModel(models.Model):
deleted_at = models.DateTimeField(null=True, default=None)
objects = SoftDeleteManager()
all_objects = models.Manager()
def soft_delete(self):
self.deleted_at = timezone.now()
self.save()
def restore(self):
self.deleted_at = None
self.save()
class Meta:
abstract = True
SoftDeleteManager
looks like this:class SoftDeleteManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(deleted_at__isnull=True)
my_note.deleted_at