2016-02-11 49 views
3

我有這些模型。防止Django的級聯刪除進行超

# models.py 
class A(models.Model): 
    name = models.CharField('Name', max_length=50) 

class B(A): 
    a_ptr = models.OneToOneField('A', primary_key=True, editable=True, parent_link=True) 
    number = models.CharField('Number', max_length=15) 

我試圖捕捉的關係是每一個B也是一個A,但一個A不一定是B.我可以用一個ForeignKey代替,但我寧願是指繼承的字段上B,比如B.name。

我打算用這些模型的方式是,將永遠是第一次實例化。每當一個B的實例,將不得不選擇一個現有的(但不是已經採取)B.

這工作得很好,到目前爲止,但我唯一的問題是與級聯刪除。通過這個設置,刪除B將刪除其相應的A(或者至少django的管理員會發生這種情況)。我怎樣才能把這個級聯關掉?

我意識到on_delete屬性,但是如果我將它設置爲,在a_ptr字段上說DO_NOTHING,它將具有允許B存在而沒有相應的A而不是其他方式的效果。

我該怎麼做?

+0

[本答案](http://stackoverflow.com/questions/3711191/django-deleting-object-keeping-parent)相當巧妙(開關'b.a_ptr'到刪除之前指向不同的實例)。我不知道是否有一種不太古怪的方式。 – Alasdair

回答

1

實際上,你可以通過keep_parents=True對模型中的刪除方法。

a = A.objects.create(name='a') 
b = B.objects.create(a_ptr=a, number='1') 

b.delete(keep_parents=True) 
assert A.objects.filter(pk=a.pk).exists() 

注意:keep_parents參數是在Django 1.9中添加的。 Django的舊版本可能需要使用this answer

+0

這些都不支持批量刪除,對嗎? – Khodeir

+0

正確,QuerySets上的'delete'方法不帶任何參數。如果您絕對需要批量刪除,您可以使用'_raw_delete' - 例如'B.objects.all()._ raw_delete(B.objects.db)' - 但這不是官方API,並且可以在任何時候改變。它也不會發送任何信號,並且級聯沒有保護。 –