我为我的 Django 项目构建了一个非常基本的私人消息模块。
我有一个消息模型,其中包括:
sender (Foreign key to the member model)
recipient (Foreign key to the member model)
message
date (Datetime of which the message was created)
Run Code Online (Sandbox Code Playgroud)
现在我的问题是我想创建一个新视图,该视图返回基于这些消息的对话列表。
我正在尝试编写一个查询,该查询返回最新消息,但在发件人 = 当前用户或收件人 = 当前用户的情况下是唯一的。这样我就有了一个最新消息列表,它应该相当于一个对话列表。我说对了还是我完全想多了?
conversations = Message.objects.filter(Q(recipient=request.user) |
Q(sender=request.user)).annotate(max=Max('date'))
Run Code Online (Sandbox Code Playgroud)
但这是返回重复的对话我从另一个堆栈溢出帖子中尝试过:
conversations = Message.objects.order_by('recipient', 'sender',
'date').distinct('recipient', 'sender')
Run Code Online (Sandbox Code Playgroud)
但我收到此错误“此数据库后端不支持 DISTINCT ON 字段”
任何帮助将不胜感激。
正如@Grimmy 在评论中所述,请发布更多信息。具体来说,请在您的答案中添加您尝试过的查询(您已经在评论中)和结果,以及结果有什么问题(您说“重复的对话;您的意思是每个对话只出现两次,还是更多?超过两次?)
对于这种情况,我想到了两种选择:
Conversation,该模型保存有关对话的信息,包括成员、开始日期等,并为每条消息添加一个外键,为其分配一个对话(从消息到对话的多对一)。这将简化您的查询,并且在需要时可以轻松扩展以适应“群聊”(只需将更多成员添加到对话中),或者诸如对话本身的图片或标题之类的内容。当您发布更多信息时,如果您愿意,我会更详细地介绍选项一。现在,我只想说,如果您收到重复的对话,其中每个对话只出现两次(一次是用户是发件人,一次是用户是收件人),那么听起来您的查询已经足够好了,并且您可以在 python 中编写一个 for 循环,对生成的对话进行排序并删除旧的重复项。只要每个用户不超过一两百个对话(听起来是这样),就不应该过多地降低性能。
但无论如何,我推荐选项二。我不得不在 Django 项目中实现类似的功能,我选择了选项 2。它极大地简化了您的查询,如下所示:
# get the conversations the user is in
conversation_list = Message.objects.filter(conversation__participants=user).order_by('-date')
# get a list of the most recent message of each conversation
message_list = conversation_list.values('conversation').annotate(
first_msg=Max('conversation__message')
)
Run Code Online (Sandbox Code Playgroud)
为了使第二行正确排序消息,请将以下内容添加到您的 Message 模型中:
class Message(models.Model):
# sender field is unchanged
# date field is unchanged (maybe rename to avoid name collisions with date module)
# message field is unchanged (maybe rename to 'content' to avoid confusion)
# make recipient many-to-many because I'd recommend having both the sender and the recipient listed as recipients,
# but you don't have to do that
recipient = models.ManyToManyField(User)
# conversation foreign key
conversation = models.ForeignKey(Conversation, blank=False, null=False)
# this simplifies sorting so the "Max('conversation__message')" line
# sorts on date rather than primary key
ordering = ["-date"]
Run Code Online (Sandbox Code Playgroud)
这是对话模型:
class Conversation(models.Model):
participants = models.ManyToManyField(User)
# example functionality you may wish to add later
group_name = models.CharField(max_length=512, default="Group", blank=False, null=False)
profile_picture = models.FileField(upload_to='uploads/', default='uploads/GroupChatIcon.jpg')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1526 次 |
| 最近记录: |