You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django聊天系统中仅显示有消息往来的用户?

Django聊天列表仅展示有消息往来用户的实现方案

1. 确认消息模型结构

首先确保你的models.py中的Message模型包含以下核心字段(如果已有,可跳过此步):

from django.db import models
from django.contrib.auth.models import User

class Message(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages')
    receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='received_messages')
    content = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-timestamp']
  • related_name用于反向关联查询,必须设置,后续视图会用到。

2. 修改视图逻辑

在views.py中替换原有的用户查询逻辑,筛选出与当前用户有过消息收发的用户:

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Max
from .models import Message
from django.contrib.auth.models import User

@login_required
def chat_list(request):
    current_user = request.user
    # 筛选条件:要么当前用户给对方发过消息,要么对方给当前用户发过消息
    contacted_users = User.objects.filter(
        Q(id__in=Message.objects.filter(sender=current_user).values_list('receiver_id', flat=True)) |
        Q(id__in=Message.objects.filter(receiver=current_user).values_list('sender_id', flat=True))
    ).exclude(id=current_user.id).distinct()

    # 可选:按最后一条消息时间倒序排列,最新聊天优先展示
    contacted_users = contacted_users.annotate(
        last_message_time=Max('sent_messages__timestamp', 'received_messages__timestamp')
    ).order_by('-last_message_time')

    return render(request, 'chat/chat_list.html', {'contacted_users': contacted_users})
  • Q查询实现逻辑或关系,覆盖收发两种场景;
  • distinct()避免同一用户因多次收发消息被重复查询;
  • annotate+Max用于获取双方最后一条消息的时间,实现排序。

3. 调整模板渲染

修改HTML模板(如chat_list.html),遍历筛选后的用户列表:

<h2>聊天列表</h2>
<ul class="chat-list">
    {% for user in contacted_users %}
        <li class="chat-item">
            <a href="{% url 'chat_detail' user.id %}" class="user-link">{{ user.username }}</a>
            <!-- 可选:展示最后一条消息预览和时间 -->
            {% with last_sent=user.sent_messages.first last_received=user.received_messages.first %}
                {% if last_sent or last_received %}
                    {% if last_sent.timestamp > last_received.timestamp %}
                        <p class="message-preview">{{ last_sent.content|truncatechars:50 }}</p>
                        <small class="message-time">{{ last_sent.timestamp|date:"Y-m-d H:i" }}</small>
                    {% else %}
                        <p class="message-preview">{{ last_received.content|truncatechars:50 }}</p>
                        <small class="message-time">{{ last_received.timestamp|date:"Y-m-d H:i" }}</small>
                    {% endif %}
                {% endif %}
            {% endwith %}
        </li>
    {% empty %}
        <li class="empty-state">暂无聊天记录</li>
    {% endfor %}
</ul>
  • 替换原有的所有用户遍历逻辑,改为使用contacted_users;
  • 可选的消息预览逻辑会对比双方最后一条消息的时间,展示最新的那条。

注意事项

  • 如果你的Message模型中sender/receiver的related_name不是sent_messages/received_messages,需同步修改视图和模板中的对应字段;
  • 若需要优化性能,可添加数据库索引(如给sender、receiver、timestamp字段加索引);
  • 确保视图使用@login_required装饰器,避免未登录用户访问。

内容的提问来源于stack exchange,提问作者Xrystik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 05:09:10