2010-10-14 12 views
14

निम्न संबंधित मॉडल का उपयोग में कास्केड विलोपन (एक ब्लॉग प्रविष्टि कई संशोधन हो सकता है):Django - ManyToManyRelation

class BlogEntryRevision(models.Model): 
    revisionNumber = models.IntegerField() 
    title = models.CharField(max_length = 120) 
    text = models.TextField() 
    [...] 

class BlogEntry(models.Model): 
    revisions = models.ManyToManyField(BlogEntryRevision) 
    [...] 

मैं कैसे Django सभी संबंधित BlogEntryRevision s को हटाना बता सकते हैं जब इसी BlogEntry हटा दी जाती है? यदि "अन्य" पक्ष की कोई वस्तु हटा दी जाती है तो डिफ़ॉल्ट रूप से ऑब्जेक्ट को कई से अधिक संबंधों में रखना प्रतीत होता है। ऐसा करने का कोई तरीका - अधिमानतः BlogEntry.delete ओवरराइड किए बिना?

उत्तर

10

मुझे लगता है कि आप एक ManyToMany रिश्ते की प्रकृति गलतफहमी कर रहे हैं। आप "इसी ब्लॉग एंट्री" को हटाए जाने के बारे में बात करते हैं। लेकिन ManyToMany का पूरा बिंदु यह है कि प्रत्येक BlogEntryRevision में एकाधिक इससे संबंधित ब्लॉगइन्ट्रीज़ हैं। (और, ज़ाहिर है, प्रत्येक ब्लॉग एंटर्री में कई BlogEntryRevisions हैं, लेकिन आप पहले से ही जानते हैं।)

आपके द्वारा उपयोग किए गए नामों से, और तथ्य यह है कि आप इस विलोपन कैस्केड कार्यक्षमता चाहते हैं, मुझे लगता है कि आप बेहतर होंगे BlogEntryRevision से BlogEntry के मानक विदेशीकी। जब तक आप उस विदेशीकी पर null=True सेट नहीं करते हैं, तब तक हटाए जाएंगे - जब ब्लॉगइन्ट्री हटा दी जाती है, तो सभी संशोधन भी होंगे।

+2

हां, मैंने स्वीकार किया कि दूसरी प्रतिक्रिया के लिए टिप्पणी में गलती। पूर्णता के लिए: एक उपयोग केस मानना ​​जो 'ManyToManyRelation' के साथ अधिक समझ में आता है, कैस्केड डिलीट करने का एक अच्छा तरीका क्या होगा? क्या गाबी पुराकारू के हटाए गए उत्तर से दृष्टिकोण काम करता है? – AndiDog

+2

हटाने ''null = True'' –

+0

पर कैस्केड-डिलीट व्यवहार' विदेशीकी 'पर नियंत्रित किया जा सकता है [' on_delete'] (https://docs.djangoproject.com/en/dev/ref/models/ फ़ील्ड/# django.db.models.ForeignKey.on_delete) (लेकिन डिफ़ॉल्ट रूप से 'CASCADE') करता है – meshy

2

आप एक custom model manager उपयोग कर सकते हैं, लेकिन प्रलेखन इंगित करने के लिए यह does do something like this already और मैं याद नहीं आ रहा है कि इस वास्तव में क्या मतलब है लगता है:

हटाने विधि, सुविधाजनक, हटाने नामित है()। यह विधि तुरंत ऑब्जेक्ट को हटा देती है और कोई वापसी मूल्य नहीं है। उदाहरण:

e.delete() 

तुम भी वस्तुओं थोक में हटा सकते हैं। प्रत्येक क्वेरीसेट में एक डिलीट() विधि है, जो के सभी सदस्यों को क्वेरीज़ेट हटा देता है।

उदाहरण के लिए, यह सब एंट्री को हटा देता है 2005 के एक PUB_DATE वर्ष के साथ वस्तुओं:

Entry.objects.filter(pub_date__year=2005).delete() 

ध्यान रखें कि इस वसीयत, जब भी संभव, एसक्यूएल, में विशुद्ध रूप से मार डाला है और इसलिए नष्ट किया () के व्यक्तिगत ऑब्जेक्ट उदाहरण को प्रक्रिया के दौरान जरूरी नहीं कहा जाएगा। आप एक कस्टम प्रदान कर दिया है एक मॉडल वर्ग पर() विधि को हटाना और सुनिश्चित करने के लिए है कि यह कहा जाता है चाहते हैं, आप "मैन्युअल" उदाहरणों इस मॉडल का (एक क्वेरीसमूह से अधिक पुनरावृत्ति को हटाने के लिए जैसे, द्वारा की आवश्यकता होगी और व्यक्तिगत रूप से प्रत्येक ऑब्जेक्ट पर हटाएं() को हटाएं ( थोक डिलीट() क्वेरी क्वेरी का उपयोग करने के बजाय।

Django एक वस्तु को हटाता है, यह एसक्यूएल हटाना कैस्केड पर बाधा के व्यवहार emulates - दूसरे शब्दों में, किसी भी जिन वस्तुओं पर था विदेशी कुंजी लिए ऑब्जेक्ट पर इंगित हटा दिया साथ हटा दिया जाएगा के साथ। उदाहरण के लिए:

b = Blog.objects.get(pk=1) 
# This will delete the Blog and all of its Entry objects. 
b.delete() 
+0

ठीक है, व्यापक हटाए गए 1 के लिए डिफ़ॉल्ट हैं: एन ('ForeignKey')' ब्लॉग 1 की तरह संबंध: उद्धृत दस्तावेज में एन Entry'। लेकिन मेरे पास 'ManyToManyRelation' है, इसलिए कैस्केड केवल रिकॉर्ड को हटा देता है जो कहता है "एंट्री एक्स और संशोधन वाई एक साथ हैं" लेकिन' BlogEntryRevision 'रिकॉर्ड नहीं है। हो सकता है कि मुझे इसे अपने उपयोग के मामले में 'विदेशीकी' के साथ करना चाहिए ... वैसे भी, प्रश्न को कई से अधिक कैस्केडिंग हटाने पर एक सामान्य प्रश्न के रूप में विचार करें। – AndiDog

8

मैं आज इस सटीक यूज-केस था:

  • मॉडल लेखक: कई प्रविष्टियों हो सकता है
  • मॉडल प्रवेश: कई लेखकों

इसके लिए हो सकता है, मैं उपयोग कर रहा हूँ एक ManyToManyRelationship।

मेरा उपयोग-मामला था: यदि मैं किसी विशेष लेखक की अंतिम प्रविष्टि को हटा देता हूं, तो इस लेखक को भी हटाया जाना चाहिए।

समाधान pre_delete signal का प्रयोग कर प्राप्त किया जा सकता है:

@receiver(pre_delete, sender=Entry) 
def pre_delete_story(sender, instance, **kwargs): 
    for author in instance.authors.all(): 
     if author.entries.count() == 1 and instance in author.entries.all(): 
      # instance is the only Entry authored by this Author, so delete it 
      author.delete() 
+0

लेखक औरent.allries.all() 'में क्यों और उदाहरण की जांच करें? आप उदाहरण के संबंध में लेखकों पर पहले से ही पुनरावृत्त कर रहे हैं। –

+0

यह एक अच्छा सवाल है, मुझे यकीन नहीं है कि मैंने इसे क्यों जोड़ा। चेक के बिना शायद यह भी संभव है। – jessepeng

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

  • कोई संबंधित समस्या नहीं^_^