Хотя использование сигнала post_delete, как описано выше Бернардо, является нормальным подходом, он будет работать хорошо, я стараюсь избегать использования сигналов настолько малым, насколько это возможно, так как мне кажется, что он излишне запутывает ваш код, добавляя поведение в стандартные функции места, которые можно ожидать.
Я предпочитаю метод переопределения выше, однако, пример, приведенный Феликсом, имеет один фатальный недостаток; функция delete (), которую она переопределяет, выглядит следующим образом:
def delete(self, using=None):
using = using or router.db_for_write(self.__class__, instance=self)
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
collector = Collector(using=using)
collector.collect([self])
collector.delete()
Обратите внимание на параметр 'using', в большинстве случаев мы вызываем delete () с пустыми аргументами, поэтому мы могли даже знать, что он там был. В приведенном выше примере этот параметр похоронен нами, переопределяя и не глядя на функциональность суперкласса, если кто-то, кому передать параметр 'using' при удалении профиля, вызовет непредвиденное поведение. Чтобы избежать этого, мы должны сохранить аргумент вместе со значением по умолчанию lika так:
class Profile(models.Model):
# ...
def delete(self, using=None):
if self.shipper:
self.shipper.delete()
if self.carrier:
self.carrier.delete()
if self.affiliat:
self.affiliat.delete()
super(Profile, self).delete(using)
Однако, один из подводных камней в подходе переопределения состоит в том, что delete () не вызывается явно для каждой записи в дБ при массовом удалении, это означает, что если вы хотите удалить несколько профилей одновременно и сохранить переопределение (например, вызывая .delete () для набора запросов django) вам нужно будет либо использовать сигнал удаления (как описано Бернардо), либо вам нужно будет перебирать каждую запись, удаляя их по отдельности (дорого и некрасиво).