2012-07-14 15 views
9

मैं Django में एक संकेत कॉलबैक है:Django अस्थायी रूप से अक्षम संकेतों

@receiver(post_save, sender=MediumCategory) 
def update_category_descendants(sender, **kwargs): 

    def children_for(category): 
     return MediumCategory.objects.filter(parent=category) 

    def do_update_descendants(category): 
     children = children_for(category) 
     descendants = list() + list(children) 

     for descendants_part in [do_update_descendants(child) for child in children]: 
      descendants += descendants_part 

     category.descendants.clear() 
     for descendant in descendants: 
      if category and not (descendant in category.descendants.all()): 
       category.descendants.add(descendant) 
       category.save() 
     return list(descendants) 

    # call it for update 
    do_update_descendants(None) 

लेकिन समारोह शरीर में मैं मॉडल MediumCategory couses कि कि संकेत फिर से भेजा जाता है पर .save() उपयोग कर रहा हूँ। मैं इसे कैसे अक्षम कर सकता हूं; सही समाधान with कथन के अंदर कुछ 'जादू' के साथ होगा।

अद्यतन: यदि कोई दिलचस्पी लेता है तो यह अंतिम समाधान है।

class MediumCategory(models.Model): 
    name = models.CharField(max_length=100) 
    slug = models.SlugField(blank=True) 
    parent = models.ForeignKey('self', blank=True, null=True) 
    parameters = models.ManyToManyField(AdvertisementDescriptonParameter, blank=True) 
    count_mediums = models.PositiveIntegerField(default=0) 
    count_ads = models.PositiveIntegerField(default=0) 

    descendants = models.ManyToManyField('self', blank=True, null=True) 

    def save(self, *args, **kwargs): 
     self.slug = slugify(self.name) 
     super(MediumCategory, self).save(*args, **kwargs) 

    def __unicode__(self): 
     return unicode(self.name) 
(...) 
@receiver(post_save, sender=MediumCategory) 
def update_category_descendants(sender=None, **kwargs): 
    def children_for(category): 
     return MediumCategory.objects.filter(parent=category) 

    def do_update_descendants(category): 
     children = children_for(category) 
     descendants = list() + list(children) 

     for descendants_part in [do_update_descendants(child) for child in children]: 
      descendants += descendants_part 

     if category: 
      category.descendants.clear() 
      for descendant in descendants: 
       category.descendants.add(descendant) 
     return list(descendants) 

    # call it for update 
    do_update_descendants(None) 

उत्तर

7

शायद मैं गलत हूँ, लेकिन मुझे लगता है कि category.save() अपने कोड में की जरूरत नहीं है, (जोड़ें) क्योंकि परिवर्तन वंशज में लेकिन श्रेणी में किया जाता है पर्याप्त है।

इसके अलावा, आप कर सकते हैं संकेत से बचने के लिए:

  • Disconnect signal और फिर से कनेक्ट।
  • उपयोग update: Descendant.objects.filter(pk = descendant.pk).update(category = category)
+0

ठीक है, मैं यही देख रहा था: 'डिस्कनेक्ट' समाधान है, इसे 'कथन' में डालकर शुद्धता का मामला है :) लेकिन 'save() 'को हटाने के बाद, डिस्कनेक्ट की आवश्यकता नहीं है। उत्तम। – bartek

+0

आप सही हैं, 'save()' की आवश्यकता नहीं है। – bartek

9

@danihp एक संकेत डिस्कनेक्ट करने में इस तरह के अद्यतन का उपयोग कर() के रूप में के बजाय() को बचाने के लिए एक सूखी और लगातार समाधान, नहीं है।

अपने मॉडल पर एक सिग्नल को अक्षम करने के लिए, आने वाले सिग्नल फायरिंग को रोकने के लिए वर्तमान उदाहरण पर एक विशेषता सेट करना एक आसान तरीका है।

यह एक सरल डेकोरेटर की जाँच करता है कि दिए गए उदाहरण 'skip_signal' विशेषता है, तो उपयोग किया जा सकता है, और यदि ऐसा है तो कहा जा रहा से विधि से बचाता है:

from functools import wraps 

def skip_signal(): 
    def _skip_signal(signal_func): 
     @wraps(signal_func) 
     def _decorator(sender, instance, **kwargs): 
      if hasattr(instance, 'skip_signal'): 
       return None 
      return signal_func(sender, instance, **kwargs) 
     return _decorator 
    return _skip_signal 

अब आप यह इस का उपयोग कर सकते रास्ता:

from django.db.models.signals import post_save 
from django.dispatch import receiver 

@receiver(post_save, sender=MyModel) 
@skip_signal() 
def my_model_post_save(sender, instance, **kwargs): 
    instance.some_field = my_value 
    # Here we flag the instance with 'skip_signal' 
    # and my_model_post_save won't be called again 
    # thanks to our decorator, avoiding any signal recursion 
    instance.skip_signal = True 
    instance.save() 

आशा है कि इससे मदद मिलती है।

+0

धन्यवाद एक गुच्छा, इससे मुझे बहुत मदद मिली। –

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