2016-08-29 2 views
4

Я пытаюсь создать простую модель уведомления/сообщения для своего приложения Django. Это будет хранить уведомления с сайта пользователю и сообщения от одного пользователя к другому. Рабочая модель, которую я использовал, выглядит так:Django: простая модель для хранения сообщений и уведомлений от пользователей

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) 

сообщение будет 0-1 отправителей (0, если сообщение является уведомлением от сайта к пользователю), и, как правило, один получателем (если уведомление предназначен для одного конкретного пользователя - например, «есть комментарий к вашей записи» - или когда сообщение было отправлено от одного пользователя к другому). Это работало для меня. Однако мне пришло в голову, что в некоторых случаях я хочу отправить уведомление каждому пользователю. Я мог бы потенциально создать Notification объектов в цикле:

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

Но это, кажется, что это будет довольно неэффективно, и создавать ненужные в базе данных.

Я экспериментировал с обновлением моей модели, как это:

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) 

Но это требует sender (по причинам, которые я не понимаю), и так как есть только одна запись для каждого уведомления, когда один получатель читает уведомление, и я установил read = True, он будет отображаться как прочитанный для всех получателей.

Есть ли простое решение, которое мне не хватает, когда я могу использовать одну модель для обработки уведомлений/сообщений, или мне придется добавить некоторые дополнительные модели (или дублировать уведомления в таблице уведомлений)?

Простите мое незнание дизайна базы данных. Это определенно слабость, над которой я работаю.

ответ

1

Моим решением является создание модели ReadFlag.

class ReadFlag(models.Model): 
    user = models.ForeignKey(User) 
    message = models.ForeignKey(Message) 
    created = ... 
+0

Я рассматривал это, но есть ли преимущество в добавлении одной записи «Message», а затем добавление записей «ReadFlag» для каждого пользователя по сравнению с одной таблицей и добавлением записи «Message» для каждого пользователя? – elethan

+0

Вы не должны клонировать содержимое сообщения. Одно сообщение -> Многие пользователи – Admdebian

-1

Вы можете попробовать:

class Notification(models.Model): 
    sender = models.ForeignKey(User, blank=True, ...) 
    ... 
1

Вы волнуетесь, что будет создавать помехи в вашей БД, но тот факт, что если вы хотите хранить информацию о имеет ли каждый пользователь read данное сообщение, для каждого сообщения вам необходимо сохранить одну запись на пользователя. Об этом нет.

Как вы хотите сохранить эти сообщения, зависит от вас. Я думаю, что ваша оригинальная модель в порядке. Решение Admdebian также прекрасно, но для этого требуется дополнительная модель. Единственный недостаток заключается в том, что он использует меньше места (но не меньше записей) в БД для ваших массовых уведомлений, но это не имеет значения, если у вашего приложения не много пользователей.

Кроме того, в вашей первоначальной модели я бы изменил поле received_date на sent_date. received_date вводит в заблуждение, потому что я предполагаю, что вы создаете запись Notification в бэкэнде, прежде чем получите подтверждение, что оно было прочитано, и вы устанавливаете это поле в текущую временную метку с auto_now_add.

Итак, измените received_date на sent_date и добавьте столбец read_date, который вы можете обновить, когда пользователь действительно прочитает сообщение.Еще лучше замените столбец readread_date, который либо None (сообщение не было прочитано), либо имеет некоторое время в нем (сообщение было прочитано в то время). Теперь вы сохраняете больше информации с тем же количеством полей.