Django演示瞭如何設置或取消在文檔中使用外鍵級聯刪除。Django級聯刪除反向外鍵
model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL)
但是如果我們想要另一種方式來解決這個問題呢?如果我們想要刪除fk模型導致刪除此模型會怎麼樣?
感謝
Django演示瞭如何設置或取消在文檔中使用外鍵級聯刪除。Django級聯刪除反向外鍵
model = models.ForeignKey(MyModel, null = True, on_delete = models.SET_NULL)
但是如果我們想要另一種方式來解決這個問題呢?如果我們想要刪除fk模型導致刪除此模型會怎麼樣?
感謝
我不認爲你正在尋找的特徵是一個ORM或數據庫的概念。您只想在刪除某些內容時執行回調。
所以使用post_delete
signal並添加有回調處理
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]
有一個非常微妙的實現角度,我認爲我應該加入討論。
比方說,我們有兩個型號,其中一個引用外鍵的另一種,如:
class A(models.Model):
x = models.IntegerField()
class B(models.Model):
a = models.ForeignKey(A, null=True, blank=True)
現在,如果我們刪除一個的條目中,級聯行爲將導致參考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
此代碼將工作無論哪種方式。我希望它能幫助一些人。
順便說一下,這可能不會導致無限遞歸,是不是? – minmaxavg
這種策略是不可靠的,因爲'delete()'方法發出'on_delete'信號,並且'delete()'方法[不保證被調用](https://docs.djangoproject.com/en/dev/topics/db/queries /#deletion-objects)「,只要有可能,這將純粹在SQL中執行,因此單個對象實例的delete()方法在進程中不一定會被調用。如果你在模型類上提供了一個自定義的delete()方法......「 – claytond