I want automatically update an external application about a change in a model. The problem is that the data is in a many2many relation between events <-> users. I tried to use the "m2m_changed" signal.
@receiver(m2m_changed, sender=models.Event.organisers.through)
def event_changed(sender, instance, action, *args, **kwargs):
if "post" in action:
# hey api here is the new list of organisers of this
The problem with this is that if i make a single change where i remove one user and add another then this code is called twice! That's no good and i can't just ignore one type of operation in case only that operation is called. I have thought pushing instances to stacks and ignoring dups but that seems messy. Is there a way i can make my own signal that only fires once?
There doesn't relay seem to be a good answer to this question so here is some useful workarounds that are better than what i was imagined in the first pace.
Instead of combining signals instead add the primary keys of the instances to a set to ignore duplicate signals:
updated = set()
@receiver(m2m_changed, sender=models.Event.organisers.through)
def event_changed(sender, instance, action, *args, **kwargs):
if "post" in action:
updated.add(instance.pk)
def send_updates():
for Event in updated: # Iteration AKA for each element
#update code here
While this requires some sort of scheduled task to run send_updates() it avoids the chance of spamming if there are many consecutive changes to the event.
Ignore signals altogether add last modified to the model. Then run a query to get all events between now and when the send_updates() was last called. Store the last called somewhere to disk/database to avoid having to resend everything on restart.