2010-07-14 9 views
5

यहां स्थिति है:django: पोस्ट-सेव सिग्नल का उपयोग करके रिकर्सन

मान लें कि मेरे पास डीजेंगो में मॉडल ए है। जब मैं किसी ऑब्जेक्ट को सहेज रहा हूं (कक्षा ए के) मुझे इस फ़ील्ड की सभी अन्य वस्तुओं में अपने फ़ील्ड को सहेजने की ज़रूरत है। मेरा मतलब है कि मुझे हर दूसरे ऑब्जेक्ट को लेट सेव की प्रतिलिपि बनाने की आवश्यकता है।

जब मैं संकेत (उदाहरण के लिए के बाद बचाने के लिए) मैं एक प्रत्यावर्तन और मेरे अजगर मरता (वस्तुओं एक दूसरे को मुझे लगता है कि को बचाने की कोशिश) मिल का उपयोग करें।

मैं पुरुषों मैं उम्मीद है कि पूर्व/संकेत के बाद बचाने में एक ही कक्षा पर .save() विधि का उपयोग कर एक प्रत्यावर्तन का कारण होता है लेकिन सिर्फ यह कैसे से बचने के लिए पता नहीं है।

हम क्या करते हैं?

+0

शायद कुछ कोड जोड़ें ताकि आपकी स्थिति स्पष्ट हो जाए? – adamk

+0

यदि आप pre_save का उपयोग करते हैं तो ऐसा नहीं होगा, क्योंकि आपको स्वयं को सहेजने के लिए कॉल नहीं करना है, तो यह तब होगा «स्वाभाविक रूप से»। –

उत्तर

4

यह काम करेगा:

class YourModel(models.Model): 
    name = models.CharField(max_length=50) 

    def save_dupe(self): 
     super(YourModel, self).save() 

    def save(self, *args, **kwargs): 
     super(YourModel, self).save(*args, **kwargs) 
     for model in YourModel.objects.exclude(pk=self.pk): 
      model.name = self.name 
      # Repeat the above for all your other fields 
      model.save_dupe() 

आप क्षेत्रों में से एक बहुत कुछ है, तो आप शायद उन पर पुनरावृति करने के लिए जब उन्हें अन्य मॉडल को कॉपी करने चाहता हूँ। मैं तुम्हें छोड़ दूंगा।

+0

क्या होता है जब मॉडल सहेजा जा रहा है उपयोगकर्ता और AFAIK इसे उपclass करने के लिए एक अच्छा विचार नहीं है। आइए कहें कि मेरे पास प्रेषक के साथ उपयोगकर्ता के रूप में post_save फ़ंक्शन है और उस फ़ंक्शन के अंदर मैं इंस्टेंस अपडेट करना चाहता हूं। कॉलिंग फिर से सहेजने के बाद post_save को ट्रिगर करेगा और स्थानीय सर्वर बंद हो जाएगा। – Marconi

+0

'model.save_dupe() 'के बजाय बेहतर अभी तक' सुपर (YourModel, मॉडल)। सेव()'। –

4

इसे संभालने का एक और तरीका है सहेजने के दौरान श्रोता को हटाना। तो:

class Foo(models.Model): 
    ... 

def foo_post_save(instance): 
    post_save.disconnect(foo_post_save, sender=Foo) 
    do_stuff_toSaved_instance(instance) 
    instance.save() 
    post_save.connect(foo_post_save, sender=Foo) 

post_save.connect(foo_post_save, sender=Foo) 
+0

आपने मेरा दिन बचाया, धन्यवाद! –

7

@ShawnFumo एक संकेत को डिस्कनेक्ट करने से खतरनाक है, तो एक ही मॉडल एक ही समय में कहीं और सहेजा जाता है, ऐसा नहीं है!

@Aram Dulyan, अपने समाधान लेकिन संकेत है जो इतना शक्तिशाली हैं उपयोग करने से रोक काम करता है!

आप प्रत्यावर्तन से बचने और संकेतों (उपयोग करते हुए) को बनाए रखना चाहते हैं, तो जाने के लिए एक आसान तरीका आगामी संकेतों फायरिंग रोकने के लिए मौजूदा उदाहरण पर एक विशेषता सेट करने के लिए है।

यह एक सरल डेकोरेटर की जाँच करता है कि दिए गए उदाहरण '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): 
    # you processing 
    pass 

m = MyModel() 
# Here we flag the instance with 'skip_signal' 
# and my_model_post_save won't be called 
# thanks to our decorator, avoiding any signal recursion 
m.skip_signal = True 
m.save() 

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

+0

अपनी बचत के बाद 'del skip_signal' को न भूलें। –

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