die*_*us9 26 django django-signals
我需要使用模型进行保存但我需要在保存信号之前断开信号的某些接收器.
我的意思是,
我有一个模特:
class MyModel(models.Model):
...
def pre_save_model(sender, instance, **kwargs):
...
pre_save.connect(pre_save_model, sender=MyModel)
Run Code Online (Sandbox Code Playgroud)
在代码中的另一个地方我需要类似的东西:
a = MyModel()
...
disconnect_signals_for_model(a)
a.save()
...
reconnect_signals_for_model(a)
Run Code Online (Sandbox Code Playgroud)
因为在这种情况下我需要保存模型而不执行函数pre_save_model.
alu*_*ach 32
对于干净且可重用的解决方案,您可以使用上下文管理器:
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
)
Run Code Online (Sandbox Code Playgroud)
现在,您可以执行以下操作:
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',
)
Run Code Online (Sandbox Code Playgroud)
注意:如果信号处理程序使用a dispatch_uid,则必须使用dispatch_uidarg.
qri*_*ris 24
您可以像Haystack在RealTimeSearchIndex中那样连接和断开信号,这看起来更标准:
from django.db.models import signals
signals.pre_save.disconnect(pre_save_model, sender=MyModel)
a.save()
signals.pre_save.connect(pre_save_model, sender=MyModel)
Run Code Online (Sandbox Code Playgroud)
我没有测试过以下代码,但它应该工作:
from django.db.models.signals import pre_save
def save_without_the_signals(instance, *args, **kwargs):
receivers = pre_save.receivers
pre_save.receivers = []
new_instance = instance.save(*args, **kwargs)
pre_save.receivers = receivers
return new_instance
Run Code Online (Sandbox Code Playgroud)
它会使来自所有发送者的信号静音但不仅仅是instance.__class__.
此版本仅禁用给定模型的信号:
from django.db.models.signals import pre_save
from django.dispatch.dispatcher import _make_id
def save_without_the_signals(instance, *args, **kwargs):
receivers = []
sender_id = _make_id(instance.__class__)
for index in xrange(len(self.receivers)):
if pre_save.receivers[index][0][1] == sender_id:
receivers.append(pre_save.receivers.pop(index))
new_instance = instance.save(*args, **kwargs)
pre_save.receivers.extend(receivers)
return new_instance
Run Code Online (Sandbox Code Playgroud)
如果您只想断开连接并重新连接一个自定义信号,则可以使用以下代码:
def disconnect_signal(signal, receiver, sender):
disconnect = getattr(signal, 'disconnect')
disconnect(receiver, sender)
def reconnect_signal(signal, receiver, sender):
connect = getattr(signal, 'connect')
connect(receiver, sender=sender)
Run Code Online (Sandbox Code Playgroud)
通过这种方式你可以做到这一点:
disconnect_signal(pre_save, pre_save_model, MyModel)
a.save()
reconnect_signal(pre_save, pre_save_model, MyModel)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12702 次 |
| 最近记录: |