2013-05-18 9 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) 

मैं कार, बाइक, बस मॉडलों में से हटाने के तरीकों को ओवरराइड करने की जरूरत है या वहाँ कुछ बेहतर तरीका है? अन्य विकल्प व्हील मॉडल पर फ़ील्ड कार, बाइक, बस बनाना है, लेकिन इससे ज्यादा समझ नहीं आती है।

उत्तर

9

यह बात है, CarWheel से लिंक, यह संबंध में निर्भर मॉडल है। इसलिए जब आप Wheel हटाते हैं, तो यह सभी निर्भर मॉडल (संबंधित Car पंक्तियों सहित) को हटा देता है। हालांकि जब आप Car हटाते हैं, क्योंकि WheelCar पर निर्भर नहीं है, तो इसे हटाया नहीं जाता है।

Django में माता पिता के संबंधों को नष्ट करने के लिए, आपको Car के delete विधि के ऊपर लिख सकते हैं:

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

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

फिर जब कर रही:

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

भी Wheel को नष्ट करेगा।

+1

समस्या कर यह नहीं कहा जा जाएगा' विधि है कि यदि आप थोक के रूप में हटाने की कार्रवाई कर यह नहीं कहा जा जाएगा 'Car.objects.filter() हटाएं()' – Rohan

+2

@ रोहन हाँ आप सही हैं। थोक हटाने के संचालन के लिए उर्फ। django दस्तावेज़ों द्वारा सलाह दी गई क्वेरीसेट्स - https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.delete django सिग्नल 'post_delete' सजावट का उपयोग करें। –

+0

@ रोहन उपरोक्त django दस्तावेज़ लिंक के लिए एक अंश निर्दिष्ट करने के लिए - >> हटाएं() विधि एक थोक हटा देता है और आपके मॉडल पर किसी भी डिलीट() विधियों को कॉल नहीं करता है। हालांकि, यह सभी हटाए गए ऑब्जेक्ट्स (कैस्केड डिलीशन सहित) के लिए pre_delete और post_delete संकेतों को छोड़ देता है। –

7

कैस्केडिंग डिलीट पहले से ही django द्वारा प्रदान किया गया है, on_delete विशेषता मान CASCADE के माध्यम से। यह OneToOneField के साथ ForeignKey के साथ भी उपलब्ध है।

ForeignKey.on_delete

जब एक वस्तु एक ForeignKey द्वारा संदर्भित नष्ट कर दिया है, जैंगो डिफ़ॉल्ट रूप से एसक्यूएल बाधा हटाना कैस्केड पर के व्यवहार emulates और भी ForeignKey युक्त वस्तु हटा देता है।

हालांकि, अपने मॉडल में आपको एक और मॉडल में OneToOneField लगा रहे हैं, इसलिए आप अपेक्षित व्यवहार नहीं देख रहे हैं।

class Car(models.Model): 
    somefields 

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

बजाय Wheel मॉडल Car में OneToOneField डाल दिया जाता है यही कारण है कि:

में अपना मॉडल बदलें। अब जब आप Car मॉडल Wheel हटाते हैं तो हटा दिया जाएगा।

अधिभावी delete() विधि के साथ समस्या यह है कि यदि आप थोक (अधिभावी `हटाना) के साथ हटाने के रूप में आपरेशन Car.objects.filter().delete()

+0

हां, यही वह है जो मैं व्हील मॉडल पर कार आदि फ़ील्ड रखने से बचना चाहता था। तो मेरे लिए सबसे अच्छा समाधान pre_delete सिग्नल को सुनने जैसा दिखता है, सभी OneToOneFields ढूंढें और उन्हें मैन्युअल रूप से हटाएं। – ChRapO

+0

@ChRapO, यह कैसे मायने रखता है यह परिभाषित करता है? यदि आप रिवर्स लिंक चाहते हैं तो आपके पास 'parent_link = True' हो सकता है। – Rohan

संबंधित मुद्दे