Django pre_save сигнал вызывается, когда commit = False - PullRequest
1 голос
/ 14 июня 2009

Я пишу приложение Django, которое будет отслеживать изменения в моделях, аналогично интерфейсу администратора. Например, я смогу отобразить список изменений в модели, которые выглядят примерно так: Changed Status from Open to Closed.

Для этого я использую сигнал pre_save, сравнивая соответствующие поля между существующим элементом в базе данных и «экземпляром», который сохраняется. Чтобы получить существующий предмет, я должен сделать sender._default_manager.get(pk=sender.pk), который кажется немного грязным, но эта часть работает.

Проблема в том, что представление об изменении этой модели дважды вызывает метод save() в форме (сначала с commit = False) - это означает, что 2 изменения регистрируются в базе данных, так как сигнал pre_save излучается дважды.

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

Ответы [ 3 ]

3 голосов
/ 15 июня 2009

Просматривая источник Django, кажется, что pre_save сигналы отправляются при каждом вызове для сохранения, даже если commit равно false. Я бы предложил вставить в первый pre_save, но добавить столбец флага в таблицу изменений, например,

class FooChanges(models.Model):
    foo = models.ForeignKey(Foo)
    dt = models.DateTimeField(default=datetime.now)
    field = models.CharField(max_length=50)
    value = models.CharField(max_length=50) # Or whatever is appropriate here
    finished = models.BooleanField(default=False)

Тогда ваш предваритель может быть:

def pre_save_handler(sender, instance):
    foo_changes, created = FooChanges.objects.get_or_create(foo=instance, finished=False, field='Status', value=instance.status)
    if not created:
        foo_changes.finished = True
        foo_changes.save()

Итак, на первом pre_save вы фактически вставляете изменение. На втором проходе вы извлекаете его из базы данных и устанавливаете флаг в значение false, чтобы убедиться, что вы не поднимете его в следующий раз Foo status изменения.

1 голос
/ 06 марта 2011
0 голосов
/ 24 мая 2011

Django Audit Log

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...