Джанго исключает модель из отправки сигналов - PullRequest
3 голосов
/ 07 января 2012

Я хотел отследить свои модели и их операции CRUD с помощью обработки сигналов post_save, delete и init, а затем сохранить запись в базе данных об этой операции.

def handle_model_saved(sender, **kwargs):
  """Trap the signal and do whatever is needed"""
  entry=CRUD_Storage()
  entry.entry='Object \"'+sender._meta.module_name+'\" was saved.'
  entry.save()

Тогда самое смешное, эторекурсия сохранений ...

Я создал модель CRUD_Storage, я хочу, чтобы она не отправляла сигналы, такие как pre (post) init, delete, save.

Ответы [ 2 ]

3 голосов
/ 07 января 2012

Я не думаю, что вы можете помешать Django отправлять эти сигналы.

Однако вы можете настроить свой обработчик так, чтобы он не регистрировал сохранения для вашей CRUD_Storage модели.

def handle_model_saved(sender, **kwargs):
    """Trap the signal and do whatever is needed"""
    if sender == CRUD_Storage:
        # return early to prevent recursion of saves
        return
    entry=CRUD_Storage()
    entry.entry='Object \"'+sender._meta.module_name+'\" was saved.'
    entry.save()
0 голосов
/ 28 ноября 2014

Вот способ DRY для отклонения сигналов.

Если вы хотите отклонить сигнал, чтобы избежать рекурсии, простой способ - установить атрибут для текущего экземпляра, чтобы предотвратить срабатывание следующих сигналов.

Это можно сделать с помощью простого декоратора, который проверяет, имеет ли данный экземпляр атрибут '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()

Надеюсь, это поможет.

...