Удаление каскада Django на внешних внешних ключах

Django показывает, как устанавливать или переопределять каскадные удаления с внешними ключами в своих документах.

model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL) 

Но что, если мы хотим, чтобы этот эффект был наоборот? Что, если мы хотим, чтобы удаление fk-модели привело к удалению этой модели?

благодаря

2 Solutions collect form web for “Удаление каскада Django на внешних внешних ключах”

Существует очень тонкая точка реализации, и я подумал, что должен добавить к этому обсуждению.

Предположим, у нас есть две модели, одна из которых ссылается на другую по внешнему ключу, как в:

 class A(models.Model): x = models.IntegerField() class B(models.Model): a = models.ForeignKey(A, null=True, blank=True) 

Теперь, если мы удалим запись A, каскадное поведение приведет к удалению ссылки в B.

Все идет нормально. Теперь мы хотим изменить это поведение. Очевидным способом, который люди упоминали, является использование сигналов, излучаемых во время удаления, поэтому мы идем:

 def delete_reverse(sender, **kwargs): if kwargs['instance'].a: kwargs['instance'].a.delete() post_delete.connect(delete_reverse, sender=B) 

Это кажется совершенным. Это даже работает! Если мы удалим запись B, соответствующий A также будет удален.

ПРОБЛЕМА заключается в том, что это имеет циклическое поведение, которое вызывает исключение: если мы удалим элемент из A из-за каскадного поведения по умолчанию (которое мы хотим сохранить), соответствующий элемент B также будет удален, что приведет к delete_reverse, который пытается удалить уже удаленный элемент!

Фокус в том, что для правильной реализации обратного каскадирования требуется ИСКЛЮЧИТЕЛЬНОЕ ОБРАБОТКА:

 def delete_reverse(sender, **kwargs): try: if kwargs['instance'].a: kwargs['instance'].a.delete() except: pass 

Этот код будет работать в любом случае. Надеюсь, это поможет некоторым людям.

Я не думаю, что функция, на которую вы смотрите, представляет собой концепцию ORM или базы данных. Вы просто хотите выполнить обратный вызов, когда что-то будет удалено.

Поэтому используйте сигнал post_delete и добавьте обработчик обратного вызова

 from django.db.models.signals import post_delete from django.dispatch import receiver from myapp.models import MyModel @receiver(post_delete, sender=MyModel) def my_post_delete_callback(sender, **kwargs): #Sender is the model which when deleted should trigger this action #Do stuff like delete other things you want to delete #The object just deleted can be accessed as kwargs[instance] 
  • Foo.objects.get (id = None) возвращает экземпляр Foo, иногда
  • pymysql connection select query и fetchall return tuple, который имеет байтовые литералы, такие как b'25.00 ', а не строки, такие как '25 .00'
  • Удалить дубликаты в списке объектов с помощью Python
  • SQLAlchemy: создать запрос на удаление с помощью самообучения в MySQL
  • Django: sqlite для dev, mysql для prod?
  • как преобразовать несколько слоев вложенной json в таблицу sql
  • Python, конвертировать 9 кортежей UTC в формат MySQL datetime
  • Как я могу сделать асинхронные операции mysql в торнадо с помощью Python3.4?
  • Python - лучший язык программирования в мире.