Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disconnect signals for models and reconnect in django

I need make a save with a model but i need disconnect some receivers of the signals before save it.

I mean,

I have a model:

class MyModel(models.Model):     ...  def pre_save_model(sender, instance, **kwargs):     ...  pre_save.connect(pre_save_model, sender=MyModel) 

and in another place in the code i need something like:

a = MyModel() ... disconnect_signals_for_model(a) a.save() ... reconnect_signals_for_model(a) 

Because i need in this case, save the model without execute the function pre_save_model.

like image 857
diegueus9 Avatar asked Feb 05 '10 17:02

diegueus9


People also ask

Are Django signals asynchronous?

To answer directly: No. It's sync.

Where is Pre_save signal in Django?

pre_save. This is sent at the beginning of a model's save() method. Arguments sent with this signal: sender.

What is the use of the Post_delete signal in Django?

Django Signals - post_delete()To notify another part of the application after the delete event of an object happens, you can use the post_delete signal.


1 Answers

For a clean and reusable solution, you can use a context manager:

class temp_disconnect_signal():     """ Temporarily disconnect a model from a signal """     def __init__(self, signal, receiver, sender, dispatch_uid=None):         self.signal = signal         self.receiver = receiver         self.sender = sender         self.dispatch_uid = dispatch_uid      def __enter__(self):         self.signal.disconnect(             receiver=self.receiver,             sender=self.sender,             dispatch_uid=self.dispatch_uid,             weak=False         )      def __exit__(self, type, value, traceback):         self.signal.connect(             receiver=self.receiver,             sender=self.sender,             dispatch_uid=self.dispatch_uid,             weak=False         ) 

Now, you can do something like the following:

from django.db.models import signals  from your_app.signals import some_receiver_func from your_app.models import SomeModel  ... kwargs = {     'signal': signals.post_save,     'receiver': some_receiver_func,     'sender': SomeModel,      'dispatch_uid': "optional_uid" } with temp_disconnect_signal(**kwargs):     SomeModel.objects.create(         name='Woohoo',         slug='look_mom_no_signals',     ) 

Note: If your signal handler uses a dispatch_uid, you MUST use the dispatch_uid arg.

like image 129
alukach Avatar answered Oct 03 '22 23:10

alukach