2013-05-18 82 views
5

在這種情況下如何執行刪除有一些聰明的方法嗎?通過OneToOneField刪除相關對象

class Bus(models.Model): 
    wheel = OneToOneField(Wheel) 

class Bike(models.Model): 
    wheel = OneToOneField(Wheel) 
    pedal = OneToOneField(Pedal) 

class Car(models.Model): 
    wheel = OneToOneField(Wheel) 

class Wheel(models.Model): 
    somfields 

car = Car()  
wheel = Wheel() 
wheel.save() 
car.wheel = wheel 
car.save() 
car.delete() # I want to delete also wheel (and also all stuff pointing via OneToOneField eg pedal) 

我需要覆蓋汽車,自行車,公交車模型的DELETE方法或者是有一些更好的辦法?其他選擇是在Wheel模型上創建汽車,自行車,公共汽車等領域,但沒有多大意義。

回答

9

這是事情,因爲Car鏈接到Wheel,它是關係中的依賴模型。因此,當您刪除Wheel時,它會刪除所有相關型號(包括相關的Car行)。但是,當您刪除Car時,由於Wheel不取決於Car,所以不會刪除它。做的時候

class Car(models.Model): 
    # ... 

    def delete(self, *args, **kwargs): 
     self.wheel.delete() 
     return super(self.__class__, self).delete(*args, **kwargs) 

然後:

爲了刪除Django的父母關係,可以覆蓋Cardelete方法

Car.objects.get(...).delete() 

也會刪除Wheel

+1

問題的首要'刪除(),它不會被稱爲'方法是,如果你做批量刪除操作,因爲它不會被調用'Car.objects.filter()。delete()' – Rohan

+2

@Rhan你是對的。對於批量刪除操作aka。由Django文檔建議的查詢集 - https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.delete使用django信號'post_delete'裝飾器。 –

+0

@Rohan對於上面的django文檔鏈接,具體摘錄 - >> delete()方法執行批量刪除,並且不會調用模型上的任何delete()方法。但是,它會爲所有已刪除的對象(包括級聯刪除)發出pre_delete和post_delete信號。 –

7

級聯刪除已由django提供,通過on_delete屬性值CASCADE。它也可用於OneToOneField以及ForeignKey

ForeignKey.on_delete

當由一個ForeignKey引用的對象是 刪除,Django的默認模仿SQL約束 ON DELETE CASCADE的行爲,並且也刪除包含 ForeignKey的對象。

但是,在您的模型中,您將OneToOneField放在另一個模型中,因此您沒有看到預期的行爲。

改變你的模型:

class Car(models.Model): 
    somefields 

class Wheel(models.Model): 
    somfields 
    car = OneToOneField(Car) 

是放在OneToOneFieldWheel模型來代替Car。現在當你刪除Car模型對應Wheel也將被刪除。

問題的首要delete()方法是,如果你做批量刪除操作Car.objects.filter().delete()

+0

是的,這就是我想避免在車輪模型上有汽車等領域。所以對我來說,最好的解決方案看起來像聽pre_delete信號,找到所有OneToOneFields並手動刪除它們。 – ChRapO

+0

@ChRapO,這是如何定義的地方?如果你想要反向鏈接,你可以有'parent_link = True'。 – Rohan