django soft delete doesn't cascade delete

你说的曾经没有我的故事 提交于 2019-12-10 17:37:08

问题


I'm using a soft delete in my django admin, done like this. The issue is that when I delete a foreign key item, that it doesn't seem to trigger the deletes for all the items it's linked to. Or maybe it does but it's not running the custom def delete I have on my model.

-If I delete a person then they are soft-deleted, but the related account is left untouched.

-If I remove the soft deletes, then when I delete a Person, the Accounts are deleted too which is correct.

So ideally when I delete a Person I'd want it to soft delete the Person and the Accounts referencing the Person to also be soft deleted(marking them inactive).

class Person(models.Model):
    description = models.CharField(max_length=100)

    def delete(self, *args, **kwargs):
        self.active = False
        self.deleted_date = datetime.now()
        self.save()

class Account(models.Model):
    name = models.CharField(max_length=50)
    person = models.ForeignKey(Person, null=True, blank=True)
    active = models.BooleanField(default=True, editable=False)

    objects = SoftDeleteManager()

    def delete(self, *args, **kwargs):
        self.active = False
        self.deleted_date = datetime.now()
        self.save()

    def __unicode__(self):
        return "%s: %s" % (self.type,self.name)

UPDATE: I have updated the question. I had not said that I'm running a soft delete on the Person model. Also added that when the def deletes are not overridden that the cascading deletes work, but when I do override the delete, the cascading doesn't trigger.


回答1:


Your Person model is not currently designed for "soft" deletes. When you delete a Person object, Django will remove all related Account objects. If you want to soft-delete Person objects, add a flag for that in the Person model. Then you need to make sure that your default Account manager excludes those accounts that are related to a soft-deleted Person object.

Edit:

  1. One approach is making the default manager exclude the objects related to inactive Person objects instead of setting them "deleted":

      class AccountManager(models.Manager): 
          def get_query_set(self):
              return self.filter(person__active=True).filter(active=True)
    
  2. Another approach would be setting your related Account objects "deleted" when a Person object is soft-deleted. For that, you could use a signal. A post-save signal on Person objects would be appropriate I think.




回答2:


An alternative solution would be to use django-softdelete, a Django package that has recently appeared on github: https://github.com/scoursen/django-softdelete

If you use the supplied SoftDeleteObject mixin for your models, deleting them will automatically result in a soft deletion also of all the related models. Even better is that it stores all models related in the soft deletion, so that you can also undelete all of them with a single undelete call.



来源:https://stackoverflow.com/questions/6569121/django-soft-delete-doesnt-cascade-delete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!