有没有更好的方法来设计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创建一条消息会创建尽可能多的用户数,所以我认为这不是一个好主意。
答案 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
字段的大小,因为它对我来说似乎很方便。
单个read
字段表示一对一消息:
我会将Receiver更改为外键并调整sender
和receiver
字段的相关名称,以表示sent-messages
和{{1}之类的连接}。
就像@ sebastian-fleck已建议我也将received-messages
字段更改为日期时间字段,它只会将您的查询集从read
更改为filter(read=True)
以获得相同的结果,你可以创建一个表示read为布尔值的属性,例如
filter(read__isnull=False)
这可能会变得更加复杂,这是我能想到的最简单的解决方案。
条件: - 只有消息,没有像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
这会超出我的时间限制,但有一些简短的提示:
def did_user_read_this_message(user, message)
receiver = message.receive_users.get(receiver=user)
return bool(receiver.is_read)
将所有内容放在一起Conversation
由Message
撰写并保留Participant
时间戳created
允许访问对话并将Participant
与User
对象相关联Conversation
持有Participant
时间戳,可用于使用消息last_read
时间戳来计算是否已读取消息( - >恼人的复杂部分和毫秒是重要)其他所有需要根据您的具体业务需求进行调整。这个场景是最灵活的,但它是很多工作(基于个人经验),并为您的架构增加了相当多的复杂性 - 我只推荐这个,如果它真的真的需要^^。