Home > Net >  Django signals @receiver POST_SAVE not working on PROD (ok on DEV)
Django signals @receiver POST_SAVE not working on PROD (ok on DEV)

Time:10-05

Getting nuts ... On dev, my signals (for sending an alert by mail) works for all save (create update) and delete. But on prod, only delete action sends an email. I didn't notice at once delete signals were working so I spent much time looking for an issue caused by firewall (blocked email outgoing).

Post Save

@receiver(post_save, sender=Navette)
def alerte(sender, instance, created, **kwargs):
    ref = instance.ref
    user = instance.user.username

    if created:
        alert(pour=['[email protected]'],
              sujet=f'Nouvelle navette pour la référence {ref} créé par {user}')
    else:
        alert(pour=['[email protected]'],
              sujet=f'Mise à jour de la navette pour la référence {ref} par {user}')

Post Delete

@receiver(post_delete, sender=Navette)
def alerte(sender, instance, **kwargs):
    ref = instance.ref
    user = instance.user
    alert(pour=['[email protected]'],
          sujet=f'La navette pour la référence {ref} a été supprimée par {user}')

just for info : alert.py

def alert(**kwargs):

    #ref = kwargs.get('ref', 'noref')
    de = kwargs.get('de', '[email protected]')
    pour = kwargs.get('pour', '[email protected]')
    sujet = kwargs.get('sujet', 'Sujet Général')
    contenu = kwargs.get('contenu', 'cf. objet du mail')
    fichier = kwargs.get('fichier', '')

    host = 'smtp.gmail.com'
    port = 465
    user = settings.EMAIL_HOST_USER
    passw = settings.EMAIL_HOST_PASSWORD

    msg = EmailMessage()
    msg['Subject'] = sujet
    msg['From'] = de
    msg['To'] = pour
    msg.set_content('HTML uniquement')

    msg.add_alternative(contenu, subtype='html')

    with smtplib.SMTP_SSL(host, port) as smtp:
        smtp.login(user, passw)
        smtp.send_message(msg)

As said almost everywhere, I declared my app not just with its name in settings.py : 'navette.apps.NavetteConfig', and registrered the app config in its __init__ -> default_app_config = 'navette.apps.ActivityAppConfig' even if I thought Ik heard it was not necessary anymore on DJANGO 3.

Finally, heres my apps.py for this app

from django.apps import AppConfig


class NavetteConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'navette'

    def ready(self):
        import navette.signals

Any idea ?

EDIT

navette.views

@login_required
def NavetteCreateView(request):
    form = NavetteDetailForm(request.POST)
    if request.method == 'POST':
        form = NavetteDetailForm(request.POST)
        if form.is_valid():
            form.save()
            navette_ref = form.cleaned_data.get('ref')
            logr.debug(f'{navette_ref} - enregistrée')
            messages.success(
                request, f'La navette {navette_ref} a bien 
        été créée.')
            return redirect('/navettes')
    else:
        form = NavetteDetailForm()

    context = {'form': form, 'title': 'Nouvelle Navette'}
    return render(request, 'navette/navette_form.html', 
context)

I checked the form_valid -> True

CodePudding user response:

This is a workaround but if you are really going nuts over this you can try using the pre_save signal instead. With pre_save you can check manually whether the instance has an id, if it doesn't have it then it's a new object.

@receiver(pre_save, sender=Navette)
def alerte(sender, instance, **kwargs):
    ref = instance.ref
    user = instance.user.username

    if not instance.id:
        alert(pour=['[email protected]'],
              sujet=f'Nouvelle navette pour la référence {ref} créé par {user}')
    else:
        alert(pour=['[email protected]'],
              sujet=f'Mise à jour de la navette pour la référence {ref} par {user}')

CodePudding user response:

It's possible that your receiver function is getting garbage-collected.

The Django docs say this on the subject:

Note also that Django stores signal handlers as weak references by default, so if your handler is a local function, it may be garbage collected. To prevent this, pass weak=False when you call the signal’s connect().

Try using @receiver(post_save, sender=Navette, weak=False)

  • Related