2011-01-17 11 views
11

को देखते हुए इन दोनों मॉडल:फ़िल्टर पर आधारित कई लोगों के रिश्ते में मैं एकाधिक ऑब्जेक्ट्स को कैसे हटा सकता हूं?

class Item(models.Model): 
    timestamp = models.DateTimeField() 

class Source(models.Model): 
    items = models.ManyToManyField(Item, related_name="sources") 

मैं एक स्रोत के आइटम के सभी पा सकते हैं एक निश्चित समय से पहले इस का उपयोग करते हुए:

source.items.filter(timestamp__lte=some_datetime) 

मैं कैसे कुशलतापूर्वक आइटम कि क्वेरी से मेल खाने के सभी निकालते हैं? मुझे लगता है कि मैं कुछ इस तरह की कोशिश कर सकते:

items_to_remove = list(source.items.filter(timestamp__lte=some_datetime)) 
source.items.remove(*items_to_remove) 

लेकिन यह है कि बुरा लगता है।

ध्यान दें कि मैं इन आइटमों को हटा नहीं सकता, क्योंकि वे अन्य स्रोतों से भी संबंधित हो सकते हैं। मैं सिर्फ विशिष्ट स्रोत के साथ अपने रिश्ते को हटाना चाहता हूं।

उत्तर

18

मुझे लगता है कि आप इसे सही पैसा हासिल करते हैं, को छोड़कर आप एक सूची में बदलने की जरूरत नहीं है।

source.items.remove(*source.items.filter(*args)) 

remove/add विधि [p1, p2, p3] के रूप में कई उदाहरणों को जोड़ें तो मैं, दांव लगाना चाहते हैं remove के लिए एक ही चला जाता है के रूप में देख रहा है निम्नलिखित

remove(self, *objs) 
add(self, *objs) 

और डॉक्स http://www.djangoproject.com/documentation/models/many_to_many/ उपयोग की तरह दिखता है तर्क एक ही हैं।

>>> a2.publications.add(p1, p2, p3) 

, निकालें समारोह दोहराता *objs से अधिक एक-एक करके थोड़ा और अधिक में खुदाई, पता चल सके कि यह मान्य मॉडल की है, अन्यथा पी के रूप में मानों का उपयोग करते है, तो एक pk__in के साथ आइटम को हटा देता है, तो मैं कर रहा हूँ हां कहने वाला, सबसे अच्छा तरीका है कि एम 2 एम टेबल को पहले ऑब्जेक्ट्स को हटाने के लिए क्वेरी करें, फिर उन ऑब्जेक्ट्स को एम 2 एम मैनेजर में पास करें।

# django.db.models.related.py 
    def _remove_items(self, source_field_name, target_field_name, *objs): 
     # source_col_name: the PK colname in join_table for the source object 
     # target_col_name: the PK colname in join_table for the target object 
     # *objs - objects to remove 

     # If there aren't any objects, there is nothing to do. 
     if objs: 
      # Check that all the objects are of the right type 
      old_ids = set() 
      for obj in objs: 
       if isinstance(obj, self.model): 
        old_ids.add(obj.pk) 
       else: 
        old_ids.add(obj) 
      if self.reverse or source_field_name == self.source_field_name: 
       # Don't send the signal when we are deleting the 
       # duplicate data row for symmetrical reverse entries. 
       signals.m2m_changed.send(sender=rel.through, action="pre_remove", 
        instance=self.instance, reverse=self.reverse, 
        model=self.model, pk_set=old_ids) 
      # Remove the specified objects from the join table 
      db = router.db_for_write(self.through.__class__, instance=self.instance) 
      self.through._default_manager.using(db).filter(**{ 
       source_field_name: self._pk_val, 
       '%s__in' % target_field_name: old_ids 
      }).delete() 
      if self.reverse or source_field_name == self.source_field_name: 
       # Don't send the signal when we are deleting the 
       # duplicate data row for symmetrical reverse entries. 
       signals.m2m_changed.send(sender=rel.through, action="post_remove", 
        instance=self.instance, reverse=self.reverse, 
        model=self.model, pk_set=old_ids) 
+0

धन्यवाद! मैं कोशिश करूँगा और देखता हूं कि यह कितना अच्छा काम करता है। अभी मैं एक ही कच्चे एसक्यूएल बयान उपयोग कर रहा हूँ (का उपयोग करते हुए "हटाएं ... का उपयोग" PostgreSQL में है, जो मुझे समझ में गैरमानक है)। – bunnyhero

+1

हाँ, ज्यादातर लोग ओआरएम पर चिपके रहना पसंद करते हैं :) –

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