Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: simple model for storing messages/notifications to/from users

Tags:

I am trying to create a simple Notification/Message model for my Django app. This will store notifications from the site to the user, and messages from one user to another. A working model I had been using looks like this:

class Notification(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='sender_notification')
    recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name='recipient_notification')
    message = models.TextField()
    read = models.BooleanField(default=False)
    recieved_date = models.DateTimeField(auto_now_add=True)

A message will have 0-1 senders (0 if the message is a notification from the site to the user), and typically one recipient (when the notification is meant for one specific user - e.g., "there is a comment on your post" - or when a message has been sent from one user to another). This had been working for me. However, it occurred to me that in some cases I want to send a notification to every user. I could potentially create Notification objects in a loop:

for user in User.objects.all():
    Notification.objects.create(recipient=user, message='message for all uses')

But this seems like it will be pretty inefficient, and create unnecessary clutter in the database.

I experimented with updating my model like this:

class Notification(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='sender_notification')
    recipient = models.ManyToManyField(User)
    message = models.TextField()
    read = models.BooleanField(default=False)
    recieved_date = models.DateTimeField(auto_now_add=True)

But this requires a sender (for reasons that I don't understand), and since there is only one record for each notification, when one recipient reads the notification and I set read = True, it will show as read for all recipients.

Is there an easy solution that I am missing where I can use a single model to handle notifications/messages, or am I going to have to add some additional models (or duplicate notifications in the notifications table)?

Forgive my ignorance of database design. It is definitely a weakness of mine that I am working on.

like image 798
elethan Avatar asked Aug 29 '16 17:08

elethan


1 Answers

You're worried it will create clutter in your DB, but the fact is if you want to store information about whether each user has read a given message, for each message you need to store one record per user. There's no way around it.

How you want to store these messages is up to you. I think your original model is fine. Admdebian's solution is also fine, but it requires an additional model. The only upside is that it uses less space (but not fewer records) in the DB for your mass notifications, but this doesn't matter unless your app has a ton of users.

Also, in your original model I would change the received_date field to sent_date. received_date is misleading, because I'm guessing you're creating the Notification record in the backend before you've received confirmation that it's been read, and you're setting that field to the current timestamp with auto_now_add.

So, change received_date to sent_date, and add a read_date column, which you can update when the user actually reads the message. Better yet, replace the read column with read_date, which is either None (message hasn't been read) or has some datetime in it (message was read at that time). You're now storing more information with the same number of fields.

like image 123
kylebebak Avatar answered Sep 22 '22 17:09

kylebebak