7

Definitions

  • SOFT DELETE - does not remove an object from the database, but appears to do so
  • HARD DELETE - removes the object completely from the database

Question

What is the best way to implement soft deletion in a codebase (specifically, a Django project)?

The simplest method I think would be to simply add:

is_deleted = models.BooleanField(default=False)

to a superclass which implements a softDeleteObject, and then override delete() to set the appropriate flags on the objects in question. Related objects would also need to inherit from the same superclass.

An alternative would be instead to delete the original, and have what amounts to an Archive object which is a representation of the deleted objects.

Analysis

The first appears to have a greater degree of simplicity, but does require some wide-ranging overrides - for example, User would have to be overridden to ensure that the foreign key relations of all deleted objects still held, and that deleting a User then didn't hard delete all their soft-deleted objects.

The second could be implemented with pre_delete signals which trigger creation of the surrogate objects. This again has some advantages (don't need to override all the delete() methods), but does require the implementation of archived versions of the models used in the project.

Which is preferable, and are there other alternatives?

Community
  • 1
  • 1
jvc26
  • 6,363
  • 6
  • 46
  • 75

1 Answers1

1

Why not to use active/deleted/status flags on the specific models where it is needed and do it this way? Or check the app django-reversion, there is probably everything you will need ;)

arulmr
  • 8,620
  • 9
  • 54
  • 69
Bruce
  • 1,380
  • 2
  • 13
  • 17
  • Well that is option 1 as in the question, however, for example, that requires overriding ```User``` as the ```delete()``` method should not remove users else it will damage all downstream FKey relations. It's certainly a possibility, but I was wondering whether there were other/better ideas ... – jvc26 Feb 19 '13 at 12:52
  • @jvc26 it depends on your usage. django-reversion has implemented the second option, you could take a look at it. I use my implementation of option 2 for archiving deleted objs such as spam users and feel happy: there is no need to rewrite manager or take care of Django Admin for whether or not displaying the deleted objs, just show them in the changelist of another model w/ notes describing reasons of delete and their `__unicode__()`s. – okm Feb 19 '13 at 13:22
  • I think that there is no general rule how to do it but it depends on given situation. Removing/disabling users can be quite complex. If you delete a user you have to decide what to do with related objects (delete or map to some prepared User like "Deleted user"). For another models like Projects you can use "completed" flag and don't show it in listing by default. Usually you don't want to delete any data. – Bruce Feb 19 '13 at 13:30
  • Thanks for the input, @Bruce, regarding the deletion of users and re-assignment of objects to their ownership, how would you go about this? The issue is of course the disabling of users, the other flags/archived versions are fairly straightforward ... – jvc26 Feb 19 '13 at 17:00
  • 1
    I think this is more complex topic that I am able to describe in some words. Disable the user account and then decide what to do with each related data. When you have for example a discussion that the user started, you can loose a lot of important content if you remove it. If you do for example {% if user.active %}{{ user.get_full_name }}{% else %}Anonymous{% endif %} or set the user to some anonymous account, you can still have some references to the user's real name in discussion posts (like "I don't agree what Billy Joe wrote..."). In such cases, write a good Terms of Service :) – Bruce Feb 25 '13 at 09:40