La señal de guardado de Django se llama dos veces a pesar de uid

He registrado mi señal con la callback utilizando el decorador @receiver

 @receiver(post_save, sender=User, dispatch_uid='ARandomUniqueString') def do_callback(sender, **kwargs): 

Puse el from app.signals import * en __init__.py y veo que se importa dos veces y no creo que haya una buena manera de solucionarlo, posiblemente debido a las installed apps en settings.py . No puedo entender por qué, a pesar de usar dispatch_uid y modelInstance.save se invoca solo una vez, aún se ejecuta do_callback dos veces. ¿Alguna sugerencia?

Ok, así que moví la importación a views.py (o models.py y mientras se importaba solo una vez, se llamaba dos veces).

El problema era que se post_save señal post_save cuando se creaba y se guardaba el objeto. No tengo idea de por qué, así que agregué una solución que ahora funciona

 created = False #Workaround to signal being emitted twice on create and save if 'created' in kwargs: if kwargs['created']: created=True #If signal is from object creation, return if created: return 

Editar:

post_save fue llamado dos veces porque usé .create(...) que es equivalente a __init__(...) y .save() .

Conclusión

dispatch_uid funciona y realizar importaciones individuales sigue siendo una buena práctica.

Tuve el mismo problema con las señales post_save y también post_delete. Parece que el objeto de sesión y el objeto LogEntry se estaban guardando, así como la creación de múltiples señales a pesar de configurar dispatch_uid.

Lo que funcionó para mí fue:

 from django.contrib.admin.models import LogEntry from django.contrib.sessions.models import Session .... if sender in [LogEntry, Session]: return else: # do your thing here 

He puesto el from app.signals import * en __init__.py

No debes poner nada en tu archivo __init__.py .

Si elimina esto de __init__.py y lo agrega a la parte inferior de su models.py , debería resolver su problema.

También debes evitar las importaciones “ciegas” from foo import *

Acabo de encontrar el mismo problema. Tengo un receptor que hace algo importante que debe hacerse solo una vez por cada nueva creación de una instancia de modelo en Django. Por lo tanto, utilicé la señal post_save , pero se estaba llamando dos veces para crear cada nueva instancia de modelo que estaba haciendo como Profile.objects.create(...) . La solución a este problema es la bandera created que viene con kwargs . A continuación, le indicamos cómo puede usar esa bandera para asegurarse de que su acción prevista se realiza solo una vez:

 @receiver(post_save, sender=Profile) def publish_auction(sender, **kwargs): if kwargs['created']: kwargs['instance'].send_email_confirmation() 

Probé la sugerencia dispatch_uid de los documentos de Django . No funcionó, pero el código que pegué arriba funciona.