Using Django Signals With Many-To-Many relationships
Sometimes it is useful to perform an action after something has been added to a many-to-many model in Django. The offical Django documentation is pretty sparse on this topic, so I figured I would document a decent solution. In the top of your models.py file, import Django signals.
Let says your models are setup as follows:
fromdjango.dbimportmodelsclassEvent(models.Model):name=models.CharField(max_length=255,help_text="Name of the event")classContact(models.Model):full_name=models.CharField(max_length=255,help_text="Full ame of the contact")events=models.ManyToManyField(Event,blank=True,null=True,help_text="Events this contact is associated with")
And now lets say you want to perform some action, say send an email, everytime a new event is added to the contact.events attribute. The code that will do this looks like this:
defm2m_send_email(signal,sender,**kwargs):"""
When someone adds/removes someone from the guestlist, you need
to create a RSVP receipt.
"""fromapps.invites.modelsimportRSVPStatisticscontact=kwargs['instance']action=kwargs['action']ifkwargs['pk_set']:events=kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])ifaction=='post_add':# send email when contact was added
elifaction=='post_remove':# send email when contact was removed
else:passmodels.signals.m2m_changed.connect(m2m_send_email,Contact.events.through)
m2m_send_email will get called every time you call contact.events.add(event); contact.save(). You can decide which action you want to support and when to send the email by checking kwargs['action'].