Django - 私人消息对话视图

时间:2017-04-29 13:08:40

标签: python django

我为我的Django项目构建了一个非常基本的私人消息传递模块。

我有一个Message模型,其中包含:

sender (Foreign key to the member model)
recipient (Foreign key to the member model)
message
date (Datetime of which the message was created)

现在我的问题是我想创建一个新视图,它会根据这些消息返回一个对话列表。

我正在尝试编写一个返回最新消息的查询,但在sender = current user或recipient = current user的情况下是唯一的。这是为了让我有一个最新消息列表,它应该相当于一个对话列表。我有没有正确的,或者我完全在想什么?

conversations = Message.objects.filter(Q(recipient=request.user) | 
Q(sender=request.user)).annotate(max=Max('date'))

但是这会返回重复的对话我从另一个堆栈溢出帖子中尝试了这个:

conversations = Message.objects.order_by('recipient', 'sender', 
'date').distinct('recipient', 'sender') 

但是我收到此错误“此数据库后端不支持DISTINCT ON字段”

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

正如@Grimmy在评论中所述,请发布更多信息。具体来说,请在您的答案中添加您尝试过的查询(评论中已有的查询)和结果,以及结果有什么问题(您说“重复的说话;您是说每次对话只显示两次或更多比两次?)

对于这种情况,我们会想到两个选项:

  1. 您可以在现有模型上运行查询,删除/排除重复项。
  2. 您可以创建一个名为Conversation的新模型,其中包含有关对话的信息,包括成员,开始日期等,并为每条消息添加一个外键,为其分配一个对话(多对一来自消息对话)。这样可以简化您的查询,并且可以轻松扩展以适应“群聊”(如果需要)(只需在对话中添加更多成员),或者对话本身的图片或标题等内容。
  3. 当您发布更多信息时,如果您愿意,我会更详细地讨论第一选项。现在,我只是说如果你得到重复的对话,其中每个对话只显示两次(一次是用户是发件人,一次是用户是收件人),那么听起来你的查询就足够了你可以在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')
    )
    

    为了使第二行正确对消息进行排序,请将以下内容添加到消息模型中:

    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"]
    

    以下是对话模型:

    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')