有没有更好的方法来设计Message模型?

时间:2017-12-06 08:49:50

标签: python django django-models

有没有更好的方法来设计Message模型?

我有一个消息模型:

class Message(models.Model):
    """
    message
    """
    title = models.CharField(max_length=64, help_text="title")
    content = models.CharField(max_length=1024, help_text="content")

    is_read = models.BooleanField(default=False, help_text="whether message is read")

    create_user = models.ForeignKey(User, related_name="messages",help_text="creator")
    receive_user = models.CharField(max_length=1024, help_text="receive users' id")

    def __str__(self):
        return self.title
    def __unicode__(self):
        return self.title

你看,我使用models.CharField存储用户的id,所以我可以知道应该收到这行消息的用户。

我不知道这种设计类型是否合适。或者有更好的方法吗?

我考虑过使用ManyToMany Field,但我认为如果用户太多,admin创建一条消息会创建尽可能多的用户数,所以我认为这不是一个好主意。

2 个答案:

答案 0 :(得分:1)

我绝对会将ManyToManyField用于receive_user。您将发现使用user_ids保持CharField更新和清理将是一场噩梦,将涉及重新实现大量现有Django功能。

我不确定我是否理解您使用ManyToManyField的潜在问题,管理员的用户将能够选择哪些用户成为邮件的收件人,它不会自动每个用户的消息。

e:另外,根据您使用的python版本(2或3),您只需要其中一个__str____unicode__

__unicode__是用于python2的方法,__str__用于python3:See this answer for more details

答案 1 :(得分:0)

所以它实际上取决于你的需求,我会改变你的消息模型。

一般更改

基于猜测:您不需要content字段

上的索引

我会将内容更改为TextField(例如,因为对于mysql上的propper索引,1024的长度已经很大了)https://docs.djangoproject.com/en/1.11/ref/databases/#textfield-limitations这里有关于此主题的更多信息。

我会增加title字段的大小,因为它对我来说似乎很方便。

1。简单 - >一个用户对一个用户

单个read字段表示一对一消息:

我会将Receiver更改为外键并调整senderreceiver字段的相关名称,以表示sent-messages和{{1}之类的连接}。

就像@ sebastian-fleck已建议我也将received-messages字段更改为日期时间字段,它只会将您的查询集从read更改为filter(read=True)以获得相同的结果,你可以创建一个表示read为布尔值的属性,例如

filter(read__isnull=False)

2。更复杂:一个用户到多个用户

这可能会变得更加复杂,这是我能想到的最简单的解决方案。

条件: - 只有消息,没有像strukture这样的对话 - 消息应该具有每个接收器的读状态

(我删除了更简单概述的说明,并根据我之前的意见更改了模型,这是基于我的经验以及我从您的示例和答案中假设的业务需求)

@property
def read(self):
    return bool(self.read_datetime)  # assumed read as a datetime is read_datetime

这个结构正在使用ManyToMany的强大功能和自定义模型,检查一下,非常强大:https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.ManyToManyField.through

tldr:我们希望每个接收器都具有读取状态,因此我们在一个单独的对象中对此进行建模

更长版本:我们利用自定义ManyToMany模型的强大功能为每个接收器提供单独的读取状态。这意味着我们需要更改代码的某些部分以适用于多对多结构,例如如果我们想知道所有接收者是否读取了消息:

@python_2_unicode_compatible
class Message(models.Model):
    title = models.CharField(max_length=160)
    content = models.TextField()

    create_user = models.ForeignKey(User, related_name="sent-messages")
    receive_users = models.ManyToManyField(User, through=MessageReceiver)

    def __str__(self):
        return 'Message: %s' % self.title

@python_2_unicode_compatible
class MessageReceiver(models.Model):
    is_read = models.Datetime(null=True, blank=True)
    receiver = models.ForeignKey(User)
    message = models.ForeignKey(Message)

如果我们想知道特定用户是否阅读了特定消息:

def did_all_receiver_read_the_message(message)
    unread_count = my_message.receive_users.filter(is_read__isnull=True).count()
    if unread_count > 0:
        return True
    return False

3。对话+消息+参与者

这会超出我的时间限制,但有一些简短的提示:

  • def did_user_read_this_message(user, message) receiver = message.receive_users.get(receiver=user) return bool(receiver.is_read) 将所有内容放在一起
  • ConversationMessage撰写并保留Participant时间戳
  • created允许访问对话并将ParticipantUser对象相关联
  • Conversation持有Participant时间戳,可用于使用消息last_read时间戳来计算是否已读取消息( - >恼人的复杂部分和毫秒是重要)

其他所有需要根据您的具体业务需求进行调整。这个场景是最灵活的,但它是很多工作(基于个人经验),并为您的架构增加了相当多的复杂性 - 我只推荐这个,如果它真的真的需要^^。

声明:

  • 这个可能是一个整体结构,我为示例做出的大多数设计决策都是基于假设,我只能提到一些或文本会很长,但随意问。
  • 请原谅任何错别字和错误,我没有机会运行代码。