Hi.
I’m building a file storing and sharing system.
I want to send email to new users added in a m2m (many to many) table, that m2m table shows which file is shared with which user.
The m2m field is used in the file model, it looks like this:
access = models.ManyToManyField(User, related_name='access', through='DicomFile_User', blank=True)
And the m2m table looks like this:
class DicomFile_User(models.Model):
dicomfile = models.ForeignKey(DicomFile, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
added_time = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['added_time']
When a file is shared with a new user, I want to send email to that user.
I thought to override save() method of the m2m table, so I can send email to new added user after saving. But save() method of m2m model doesn’t even run.
How do I send email to users when a new value is added to that m2m table?
You have (at least) two options I can see at the moment:
1 Like
You marked it as a solution.
Could you share which one you used and the working code?
That would really help me and others learn from your experience
Yes, I used m2m_changed signal.
Here’s the code
// DicomFile_User mode, a custom many to many table connecting DicomFile and User instances
// Normally you don't need such tables, but I wanted to add extra column named "added_time".
class DicomFile_User(models.Model):
dicomfile = models.ForeignKey(DicomFile, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
added_time = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['added_time']
//The handler
def access_changed(sender, action, pk_set, instance, **kwargs):
if action == 'post_add':
recipient_list = list()
for pk in pk_set:
user = instance.access.get(id=pk)
recipient_list.append(user.email)
params = {'dicom_file': instance, 'host': constants.HOST} //constants is just custom py file I wrote myself to keep some cosntant values
email_title = f"{instance.owner} shared a DICOM file with you"
msg_plain = render_to_string('dicoms/shared_dicom_email.txt', params)
msg_html = render_to_string('dicoms/shared_dicom_email.html', params)
send_mail(
email_title,
msg_plain,
"test@medimageshub.com",
recipient_list,
html_message=msg_html)
// Here's the call
m2m_changed.connect(access_changed, sender=DicomFile_User)
DicomFile_User is custom model for a ManyToMany table
You just have to put this on DicomFile model:
access = models.ManyToManyField(User, related_name='access', through='DicomFile_User', blank=True)
1 Like
Thank you That really helps us all learn