Vaibhav Shah
Vaibhav Shah

Reputation: 131

Soft delete django database objects

Suppose that I have django models such A ->B ->C ->D in the default database.

C is a foreign key in D,similarly B in C and C in A.

On the deletion of the object A,the default behaviour of Django is that all the objects related to A directly or indirectly will get deleted automatically(On delete cascade).Thus, B,C,D would get automatically deleted.

I want to implement deletion in a way such that on deletion of an object of A it would get moved to another database named 'del'.Also along with it all other related objects of B,C,D will also get moved.

Is there an easy way of implementing this in one go?

Upvotes: 6

Views: 6709

Answers (4)

dr. Neox
dr. Neox

Reputation: 431

maybe you could try https://github.com/drneox/django-paranoid

allows to perform soft delete and also revert it.

Use:

from django_paranoid.admin import ParanoidAdmin

class MyModelAdmin(ParanoidAdmin):
    pass

soft delete:

m = MyModel.objects.last()
m.delete()

m = MyModel.objects.last()
>>> m
>>>

get deleted object:

m = MyModel.objects_with_deleted.last()
>>> m
<MyModel: name>
>>> m.deleted_at
datetime.datetime(2019, 8, 10, 6, 16, 44, 633727, tzinfo=<UTC>)

restore object:

 m.restore()

hard delete:

m = MyModel.objects.last()
m.delete(True)

Upvotes: 0

iankit
iankit

Reputation: 9342

There is a library that matches django's default delete behavior on soft deletes. (ie uses the Cascade, do nothing, etc options from the model specification).

https://github.com/upgrad/django-deletes

PS: The library is still in beta mode, but active development.

Upvotes: 0

Vaibhav Shah
Vaibhav Shah

Reputation: 131

I have implemented this thing using a deleted flag on each model of my database instead of moving things to separate database as follows:

deleted = models.BooleanField(default=False)

And defined a soft_del function for each model as follows:

def soft_del(self):
        self.deleted = True            
        self.save()

So the deleted models would exist in the same database with deleted flag set to True.

Also to produce an ON DELETE CASCADE effect I have added such soft_del functions to each model and given a related_name to each foreign key in the model as follows:

class B(models.Model)
    a =  models.ForeignKey(A,related_name='related_Bs'))

and then call the soft_del of child when inside the soft_del of parent as follows:

def soft_del_A(self):
    self.deleted = True 
    for b in A.related_Bs.all():
        b.soft_del_B()

    self.save()

Upvotes: 7

Eugene Soldatov
Eugene Soldatov

Reputation: 10135

Just override delete method of model A and check relation before delete. If it isn't empty - move object to another table/DB.

Upvotes: 2

Related Questions