How to fire an automatic email through Django when you receive a new value in the database?

Asked

Viewed 286 times

2

Hello, my system is monitoring a server services, when a service fails I get a new value in the database with status "8" which means error, I would like to send an email to some user stating this failure, I’ve heard of Django’s Signals, however, I have no idea how to implement this.

Follow my models.py

class Executionresults(models.Model):
    id = models.UUIDField(db_column='ID', primary_key=True)  # Field name made lowercase.
    taskid = models.UUIDField(db_column='TaskID')  # Field name made lowercase.
    executionid = models.UUIDField(db_column='ExecutionID')  # Field name made lowercase.
    appid = models.ForeignKey(Apps, on_delete=models.CASCADE, db_column='AppID')  # Field name made lowercase.
    executingnodeid = models.UUIDField(db_column='ExecutingNodeID')  # Field name made lowercase.
    status = models.IntegerField(db_column='Status')  # Field name made lowercase.
    starttime = models.DateTimeField(db_column='StartTime')  # Field name made lowercase.

1 answer

1


Use Django-model-utils

pip install django-model-utils

Add a field to make tracking in its model, and overrides the method save, your class would look like this:

from model_utils import FieldTracker

class Executionresults(models.Model):
    id = models.UUIDField(db_column='ID', primary_key=True)
    taskid = models.UUIDField(db_column='TaskID')
    executionid = models.UUIDField(db_column='ExecutionID')lowercase.
    appid = models.ForeignKey(Apps, on_delete=models.CASCADE, db_column='AppID')  
    executingnodeid = models.UUIDField(db_column='ExecutingNodeID') 
    status = models.IntegerField(db_column='Status')
    starttime = models.DateTimeField(db_column='StartTime')

    # Acrescente o campo abaixo
    tracker = FieldTracker(fields=['status'])

    # Sobrescreva o metodo save 
    def save(self, *args, **kwargs):
        # Cheque se o campo foi alterado 
        if bool(self.tracker.changed()):
            # Envie o email aqui

        # Salve os dados normalmente
        uper().save(*args, **kwargs)

At the indicated point call the code for sending the email.

You can also, instead of just checking if the field has changed, compare it as the error value, in which case save would look like this:

    # Sobrescreva o metodo save 
    def save(self, *args, **kwargs):
        # Cheque se o campo recebeu o valor do erro 
        if self.tracker.changed()['status']==8:
            # Envie o email aqui

        # Salve os dados normalmente
        uper().save(*args, **kwargs)

To learn more about Fieldtrakcer, access this link.

Edited (07/03/19) [Experimental]: Superimposing the method __init__

class Executionresults(models.Model):
    # ... Definição dos campos anteriores
    status = models.IntegerField(db_column='Status')
    starttime = models.DateTimeField(db_column='StartTime')

    # Acrescente a variável abaixo
    __status_original = None

    # Sobrescreva o metodo __init__
    def __init__(self, *args, **kwargs):
        super(Executionresults, self).__init__(*args, **kwargs)
        # guarde o valor do status 
        self.__status_original = self.status

    def save(self, force_insert=False, force_update=False, *args, **kwargs):
        # Cheque se o campo foi alterado 
        if self.status != self.__status_original:
            # Envie o email aqui

        # Salve os dados 
        super(Executionresults, self).save(force_insert, force_update, *args, **kwargs)
        self.__status_original = self.status
  • It worked Sidon, thank you very much for the help, I would like to take another doubt, I work with more than 2 different databases, when I run this function in the models that is with the 'default' database works perfectly, however when I run on a models that is with postgree I do not receive any email and also do not receive any error, it would be necessary to specify the database that is for it check the change ?

  • What is the "default bank"? Have you tried to do a minimum test only with a table on test posts?

  • The default database is sqlite, already tested in a test table in postgres and did not roll.

  • I was testing some things and it seems that it works only when I edit the value and click save on admin, so it recognizes in the postgres bank, but if that value comes from the system it does not recognize.

  • Okay, let’s try to save the field and compare before saving, I’ll edit the answer but I have no way to test, test me if it works.

  • Beauty Sidon, as soon as you edit I test here, thanks again so much for the help.

  • Editatdo, see if it works.

  • Sidon, I tested it and now even when I save it fires the email, now I’m more curious to know what might be happening.

  • As I said I can not take the test today, but I remember that before posting the first option I did the test and, although it was not with postgres, it was not by the admin and it worked. Try, instead of sending an email, to test with a command like print('Funcionou') to see what happens.

  • Tested here with postgres, works with both options.

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.