【问题标题】:Django - Private messaging conversation viewDjango - 私人消息对话视图
【发布时间】:2017-04-29 13:08:39
【问题描述】:

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

我有一个消息模型,它包括:

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

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

我正在尝试编写一个返回最新消息但唯一的查询,其中发件人 = 当前用户或收件人 = 当前用户。这样我就有了一个最新消息列表,它应该相当于一个对话列表。我是不是说对了,还是我完全想多了?

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 字段”

任何帮助将不胜感激。

【问题讨论】:

  • 不清楚您在这里需要什么帮助。您在编写查询时遇到问题吗?你知道如何制作视图吗?到目前为止你有什么?
  • 嗨,葛莱米。抱歉解释不好。我在查询时遇到问题。我使用 MySQL 作为数据库平台。
  • 显示你目前拥有的东西。粘贴模型和查询,以便我们了解详细信息。
  • 老实说,我没有太多话要说。我正在努力让逻辑与 Django 一起正常运行。我试过这个: 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 字段通过这个数据库后端”

标签: python django


【解决方案1】:

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

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

  1. 您可以在现有模型上运行删除/排除重复项的查询。
  2. 您可以创建一个名为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')
)

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

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

【讨论】:

  • 嗨,布伦丹。感谢您的回答。我曾想过这个。这只是意味着我必须重组一些事情。
  • 是的,它有其优点和缺点,但缺点主要是添加新模型、重构一些现有代码和进行数据库迁移的前期工作。我认为从长远来看它会简化你的项目。
  • 谢谢伙计。非常感谢。
  • 为什么在消息模型中推荐manytomany receiver?
  • @cikatomo 我建议将接收者-消息关系设为多对多,主要有两个原因:1,我认为它简化了为用户获取消息的过程,因为不是在给定 user_id 是接收者的情况下获取消息或发件人,您可以获取该用户是收件人的消息,无论他们是否是发件人。 2,它可以轻松扩展“群聊”的可能性,其中消息可以有多个收件人(除了发件人)。但如果你不实施群聊,这个决定完全取决于你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 2014-02-18
相关资源
最近更新 更多