I want to send an email when a specific field is changed in a model. Is it possible? Here is what I am looking for. I have a profile model that includes a BooleanField that when the administrator selects to be true I want to send user an email. I know I could put it in a "def save(self):" but, that fires off an email anytime the model is changed and the field is true. Is there a way to have it only email if the field was changed from False to True?
Asked
Active
Viewed 8,478 times
4 Answers
14
save method is a perfectly good place for what you want to do:
def save(self):
if self.id:
old_foo = Foo.objects.get(pk=self.id)
if old_foo.YourBooleanField == False and self.YourBooleanField == True:
send_email()
super(Foo, self).save()

Reinoud van Santen
- 146
- 9

Sergey Golovchenko
- 18,203
- 15
- 55
- 72
-
I might change the if statement to this: if not old.field == self.field: – ShawnMilo Jul 21 '09 at 16:21
-
He wants to send email only when the value changed from False to True. So checking that values are not equal is not enough. – Sergey Golovchenko Jul 21 '09 at 16:37
-
Was looking for a way to trigger any action when a model is changed ... looks like this is it. Thanks. – Matt Miller Sep 25 '09 at 17:42
-
4The one disadvantage to overriding save here is this: the send_email() call will be blocking until it finishes executing. The user might have to wait a non-trivial amount of time, before the page loads again. If that's not a concern, then this is fine; otherwise, I'd suggest the signal approach mentioned below. – mkelley33 Jan 28 '12 at 23:23
-
I retract my statement about the signal approach after reading the comment about the changing value. See also: http://stackoverflow.com/questions/1355150/django-when-saving-how-can-you-check-if-a-field-has-changed See the answer with > 20 votes by Josh. You might want to look at something like django-celery-email if you think wait times for sending mail might be a problem. – mkelley33 Jan 29 '12 at 00:26
6
You can use django-model-changes to do this without an additional database lookup:
from django.db import models
from django.dispatch import receiver
from django_model_changes import ChangesMixin
class MyModel(ChangesMixin, models.Model):
flag = models.BooleanField()
@receiver(pre_save, sender=MyModel)
def send_email_if_flag_enabled(sender, instance, **kwargs):
if instance.previous_instance().flag == False and instance.flag == True:
# send email

Robert Kajic
- 8,689
- 4
- 44
- 43
0
Something like this could help and only sends an email when change from false to true
#models.py
from django.contrib.auth.models import User
from django.db.models import signals
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import pre_save
from django.conf import settings
from django.core.mail import send_mail
#signal used for is_active=False to is_active=True
@receiver(pre_save, sender=User, dispatch_uid='active')
def active(sender, instance, **kwargs):
if instance.is_active and User.objects.filter(pk=instance.pk, is_active=False).exists():
subject = 'Active account'
mesagge = '%s your account is now active' %(instance.username)
from_email = settings.EMAIL_HOST_USER
send_mail(subject, mesagge, from_email, [instance.email], fail_silently=False)

M. Gar
- 889
- 4
- 16
- 33
-1
Use hook a function with your models post_save using django signals (http://docs.djangoproject.com/en/dev/ref/signals/#django.db.models.signals.post_save)
In that function use standard django mailing: http://docs.djangoproject.com/en/dev/topics/email/

sharjeel
- 5,825
- 7
- 34
- 49
-
3You will not have the old value in post_save, so there wouldn't be any way of knowing if the value has actually changed or not. – Sergey Golovchenko Jul 21 '09 at 16:44