如何向用户对话显示每个用户的最后一条消息以保留聊天记录?

时间:2017-01-07 21:44:01

标签: python django django-views django-filter

我正在创建一个私人用户进行用户聊天,为了与某人聊天,联系用户必须在他自己的网址上输入他想与之交谈的用户的用户名。

既然已经建立了这个系统,我想保留聊天记录,以便以后我可以发送聊天通知。要做到这一点,我需要获取每个对话的最后一条消息,并且我想在已连接用户自己的聊天配置文件中显示它。

如下图所示:

enter image description here

模型 renderInput字段为:userCommentrecipientsendercomment

views.py

sent_at

models.py

def inbox(request, username):
    username = User.objects.get(username=username)
    connected_user = request.user

    if username == connected_user:

        #I'm having the issue on this line
        users = userComment.objects.filter(Q(client=request.user) | Q(worker=request.user)).order_by(?) 

    else:
        users = userComment.objects.filter(Q(Q(client=request.user) & Q(worker=username)) | Q(Q(client=username) & Q(worker=request.user))).order_by('sent_at')

问题:如何过滤和订购我的观点?

3 个答案:

答案 0 :(得分:1)

首先在您的userComment模型中添加反向关系的相关查询名称

class UserComment(models.Model):
    sender = models.ForeignKey(User, related_name='sender', related_query_name='s')
    recipient = models.ForeignKey(User, related_name='recipient', related_query_name='r')
    sent_at = models.DateTimeField(auto_now_add=True)
    comment = models.TextField()

现在在views.py中使用此查询:

user = request.user

users = User.objects.filter(Q(r__sender=user) | Q(s__recipient=user)).distinct().extra(select={'last_message_time': 'select MAX(sent_at) from appname_usercomment where (recipient_id=auth_user.id and sender_id=%s) or (recipient_id=%s and sender_id=auth_user.id)'}, select_params=(user.id, user.id,)).extra(order_by=['-last_message_time']).extra(select={'message': 'select comment from appname_usercomment where (sent_at=(select MAX(sent_at) from appname_usercomment where (recipient_id=auth_user.id and sender_id=%s) or (recipient_id=%s and sender_id=auth_user.id)) and ((recipient_id=auth_user.id and sender_id=%s) or (recipient_id=%s and sender_id=auth_user.id)))',}, select_params=(user.id, user.id,user.id, user.id,))

根据模型所在的app的名称,将appname设置为extra。

现在您可以按如下方式访问它:

for user in users:
    print user.username
    print user.last_message_time
    print user.message

答案 1 :(得分:0)

def inbox(request, username)    
    # first select all the comments related to user
    user = User.objects.get(username=username)
    related = userComment.objects.filter(q(client=user) | q(worker=user)).order_by('-sent_at')

    # This selects the latest comments.
    # Now loop over the related comments and group them.
    chats = {}
    for comment in related:
        if comment.client == user:
            previous_chat_history = chats.setdefault(comment.worker.username, [])
            if not len(previous_chat_history) >= 3:
                previous_chat_history.append(comment)
        if comment.worker== user:
            previous_chat_history = chats.setdefault(comment.client.username, [])
            if not len(previous_chat_history) >= 3:
                previous_chat_history.append(comment)

    # Reverse each list to keep the latest message last
    for k, v in chats.items():
        chats[k] = v.reverse()

    return render(request, 'template.html', context={chats: chats}) 

答案 2 :(得分:0)

[更新]:我刚刚意识到此解决方案仅适用于Postgresql,因为它使用distinct中的字段名称。

您可以混合使用order_bydistinct来获得所需的结果:

  1. 过滤用户为clientworker的评论:

    comments = userComment.objects.filter(Q(client=request.user) | Q(worker=request.user))
    
  2. 使用clientworkersent_at字段对用户评论进行排序。确保sent_at字段的降序排序,以便每个客户 - 工作人员对的最新评论位于顶部:

    comments = comments.order_by('client', 'worker', '-sent_at')
    
  3. 现在,获取不同的行:

    comments = comments.distinct('client', 'worker')
    

    这将仅保留第一行,即每个客户端 - 工作者对的最新注释,并从查询集中删除其余行。

  4. 在一个声明中:

    comments = userComment.objects \
                  .filter(Q(client=request.user) | Q(worker=request.user)) \
                  .order_by('client', 'worker', '-sent_at') \
                  .distinct('client', 'worker')
    

    这会为您提供用户为clientworker的每个对话的最新评论。