2014-02-17 2 views
5

Я использую pre_save и post_save сигналы для отправки аналитики в Mixpanel. Я предпочитаю, чтобы это было отделено от метода сохранения моей модели.Django: передача переменных из pre_save в сигналы post_save

Есть ли способ сохранить старые значения экземпляра при возникновении сигнала pre_save, а затем проверить новые значения против них на post_save?

Мой код выглядит следующим образом:

@receiver(pre_save, sender=Activity) 
def send_user_profile_analytics(sender, **kwargs): 
    activity_completed_old_value = kwargs['instance'].is_completed 
    # store this value somewhere? 

@receiver(post_save, sender=Activity) 
def send_user_profile_analytics(sender, **kwargs): 
    if kwargs['instance'].is_completed != activity_completed_old_value: 
     # send analytics 

Для меня это кажется более надежным, чтобы использовать post_save отправить аналитику чем pre_save, но в тот момент я не могу увидеть, что изменилось в экземпляре модели. Я хотел бы предотвратить использование глобалов или реализовать что-то в функции сохранения моей модели.

ответ

5

Вы можете сохранить их как атрибуты экземпляра.

@receiver(pre_save, sender=Activity) 
def send_user_profile_analytics(sender, **kwargs): 
    instance = kwargs['instance'] 
    instance._activity_completed_old_value = instance.is_completed 

@receiver(post_save, sender=Activity) 
def send_user_profile_analytics(sender, **kwargs): 
    instance = kwargs['instance']  
    if instance.is_completed != instance._activity_completed_old_value: 
     # send analytics 

Таким образом, вы «отправить аналитику» только если is_completed изменения во save (это означает, что save не просто хранить значение, но делает некоторую дальнейшую разработку).

Если вы хотите, чтобы выполнить действие при изменении поля во время экземпляра жизненного времени (то есть с момента его создания до save) следует хранить начальное значение при post_init (а не pre_save).

+0

Я уже думал об этом, но это хорошая практика для Django? И почему я должен сделать это защищенным атрибутом? Спасибо за подсказку post_init, это действительно лучше. – jvannistelrooy

+0

@jvannistelrooy: нет необходимости в защищенном атрибуте, но лучше не использовать эти дополнительные атрибуты вне этих функций, потому что они являются просто служебными полями. Я нашел это решение где-то ... Я отправлю ссылку, как только найду ее – Don

+1

Не могли бы вы также объяснить, почему 'post_init' лучше, чем' pre_save'? Разве это не добавило бы дополнительных запросов db, даже если значение фактически не требуется? –

Смежные вопросы