Django - how do I _not_ dispatch a signal?

烂漫一生 提交于 2019-12-04 09:43:54
Сыч

A quick and dirty solution would be:

from django.db.models.signals import post_save
from somewhere_in_my_app import my_post_save_handler

post_save.disconnect(my_post_save_handler)
instance.save()
post_save.connect(my_post_save_handler)

But otherwise i strongly recommend moving your logic into the save() method of your model.

Izz ad-Din Ruhulessin

You can disconnect and reconnect the signal. Try using a with: statement with this utility class:

class SignalBlocker(object):
    def __init__(self, signal, receiver, **kwargs):
        self.signal = signal
        self.receiver = receiver
        self.kwargs = kwargs

    def __enter__(self, *args, **kwargs):
        self.signal.disconnect(self.receiver)

    def __exit__(self, *args, **kwargs):
        self.signal.connect(self.receiver, **self.kwargs)

You can now use:

with SignalBlocker(post_save, my_post_save_handler):
    instance.save()
Sergey Podushkin

I found simple and easy solution:

MyModel.objects.filter(pk=instance.id).update(**data)

It is due to (https://docs.djangoproject.com/en/1.5/ref/models/querysets/#update):

Finally, realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals (which are a consequence of calling Model.save()).

You can also call instance.save_base(raw=True) and check for the raw argument in your pre_save or post_save signal handler:

def my_post_save_handler(instance, raw, **kwargs):
    if not raw:
        heavy_logic()

You can add some sugar and get your perfect interface:

class MyModel:
    def save(self, dispatch_signal=True, **kwargs):
        self.save_base(raw=not dispatch_signal, **kwargs)

Note that save_base() is not part of the public API of Django, so it might change in a future version.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!