I have a Abstract Model SoftDelete like follow.
class SoftDeleteManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_deleted=False)
class SoftDeleteModel(models.Model):
is_deleted = models.BooleanField(default=0)
deleted_at = models.DateTimeField(null=True)
objects = SoftDeleteManager()
def delete(self):
self.is_deleted = True
self.deleted_at = timezone.now()
self.save()
class Meta:
abstract = True
class Employee(SafeDeleteModel):
pass
Whenever model gets deleted i set is_deleted
to True
and updating the timestamp deleted_at
, and created the custom manager to override initial queryset which return only non deleted fields(is_deleted=False).
employee = Employee.objects.get(pk=1)
employee.delete()
employee.refresh_from_db() // not raising DoesNotExist
But lets say i have a Employee
model which uses the SafeDeleteModel
for soft delete, after deleting the model like Employee.objects.get(pk=1).delete()
when i call employee.refresh_from_db()
,its not raising DoesNotExist
, but updates the value of is_deleted, deleted_at as expected, what mistake i made here, why its not raising DoesNotExist
?
There's been a change in Django 2.1: refresh_from_db()
now uses a model's _base_manager
, not the _default_manager
anymore, like for related queries. This to ensure an object can be refreshed even if it cannot be found by the default manager.
So you should set your SoftDeleteManager
as the base manager using base_manager_name
. But note this comment:
Base managers aren’t used when querying on related models. For example, if the
Question
model from the tutorial had adeleted
field and a base manager that filters out instances withdeleted=True
, a queryset likeChoice.objects.filter(question__name__startswith='What')
would include choices related to deleted questions.
Also I don't know how you would retrieve any object that has been deleted after you make this change, except if you make a special manager to not filter the deleted objects (e.g. deleted_objects
).
Note also that I would expect the safedelete package you referred to in your comments to have the same issue, as it's not changing the _base_manager
either.