對於清潔和可重複使用的解決方案,你可以使用一個上下文管理器:
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
)
現在,你可以這樣做以下:
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',
)
注:如果你的信號處理程序使用dispatch_uid
,你必須使用dispatch_uid
arg。
太好了。這是最優雅的解決方案。您可以在代碼的多個部分重用上下文管理器。 – 2014-10-10 18:43:46
當接收器連接到信號時,一個小警告:'weak = False'不是默認設置。 – spg 2016-03-18 19:13:57
'weak'是[棄用](https://docs.djangoproject.com/en/1。10 /主題/信號/#斷開信號) 此外,人們應該意識到,禁用信號將阻止* all *實例觸發信號,而不僅僅是當前上下文(即其他線程,因爲信號似乎是線程安全的) ,建議[這裏](http://stackoverflow.com/questions/577376/django-how-do-i-not-dispatch-a-signal#comment64533494_10881618) – 2016-08-28 12:56:29