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

如何实现双向好友关系在各自用户好友列表中正确展示?

问题描述

开发类似Facebook的好友功能,支持发送好友请求、接受后互为好友,但目前无法实现双向好友展示——用户A与B成为好友后,无法互相出现在对方的好友列表中,当前逻辑仅能单向展示(要么显示add_to关联用户,要么显示added_from关联用户),需要基于现有add_to和added_from属性实现双向展示。


现有代码实现

models.py

class AddToNetwork(models.Model):
    NETWORK_CHOICES = (
        ('ADD', 'Add'),
        ('ACCEPT', 'Accept'),
        ('DELETE', 'Delete'),
    )
    id = models.UUIDField( primary_key = True, default = uuid.uuid4,editable = False)
    add_to = models.ForeignKey(User, on_delete=models.CASCADE,  related_name="add_to", null=True, blank=True)
    added_from = models.ForeignKey(User, on_delete=models.CASCADE, related_name="add_from", null=True, blank=True)
    network_status = models.CharField(max_length=30, choices = NETWORK_CHOICES)
    added_at = models.DateTimeField(auto_now_add = True)
    deleted_at = models.DateTimeField(auto_now = True)

    def __str__(self):
        return str(self.add_to)

发送好友请求视图

def addToNetwork(request, id):
    try:
        add_to = User.objects.get(id = id)
        current_user = User.objects.get(id = request.user.id)
        network = AddToNetwork.objects.create(add_to = add_to, added_from=current_user,network_status = 'ADD')
        messages.success(request,f'Request Sent to {add_to.first_name} {add_to.last_name}')
        return redirect('userProfileDetail', id)
    except User.DoesNotExist:
        add_to = None
    return render(request,'network/network_userProfile.html')

接受好友请求视图

def acceptNetworkRequest(request, id):
    try:
        friend_request = AddToNetwork.objects.get(id = id)
        friend_request.network_status = 'ACCEPT'
        friend_request.save()
        messages.success(request, f'You accepted {friend_request.added_from.first_name} as a friend!')
        return redirect('friends', id)

    except AddToNetwork.DoesNotExist:
        return render(request,'network/friendRequestList.html')

好友列表展示视图

def friends(request, id):
    user = User.objects.get(id = request.user.id)
    if user:
        approved_friends = AddToNetwork.objects.filter(Q(added_from_id = user),network_status = 'ACCEPT')
    context = {
        'friends': approved_friends,
    }
    return render(request, 'friend_list.html', context)

好友列表模板

{% for friend in friends %}
  <tr>
    <td>{{friend.add_to.first_name}} {{friend.add_to.last_name}}</td>
  </tr>
{% endfor %}

User模型

class User(AbstractUser):
    username = None
    id = models.UUIDField( primary_key = True, default = uuid.uuid4,editable = False)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.CharField(max_length=50, unique=True)
    created_at = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    friends = models.ManyToManyField("self", blank=True)

解决方案

1. 修正好友列表查询逻辑

当前查询仅覆盖了「当前用户是请求发送方」的情况,漏掉了「当前用户是请求接收方」的场景。通过Q查询同时包含两种情况,再提取对应的好友用户:

from django.db.models import Q

def friends(request, id):
    current_user = request.user
    # 查询所有已通过的好友关系:要么当前用户是发送方,要么是接收方
    approved_relations = AddToNetwork.objects.filter(
        Q(added_from=current_user, network_status='ACCEPT') |
        Q(add_to=current_user, network_status='ACCEPT')
    )
    # 提取好友对象,避免重复
    friends = []
    for relation in approved_relations:
        friend = relation.add_to if relation.added_from == current_user else relation.added_from
        if friend not in friends:
            friends.append(friend)
    context = {
        'friends': friends,
    }
    return render(request, 'friend_list.html', context)

2. 调整模板显示

现在friends是直接的User对象列表,模板可以简化:

{% for friend in friends %}
  <tr>
    <td>{{friend.first_name}} {{friend.last_name}}</td>
  </tr>
{% endfor %}

3. 可选:利用User模型的ManyToMany字段优化

如果希望查询更高效,可以在接受请求时同步更新friends多对多关系,后续查询好友列表会更简洁:

修改接受请求视图:

def acceptNetworkRequest(request, id):
    try:
        friend_request = AddToNetwork.objects.get(id = id)
        friend_request.network_status = 'ACCEPT'
        friend_request.save()
        # 同步更新双向好友关系
        requester = friend_request.added_from
        receiver = friend_request.add_to
        requester.friends.add(receiver)
        receiver.friends.add(requester)
        messages.success(request, f'You accepted {requester.first_name} as a friend!')
        return redirect('friends', request.user.id)

    except AddToNetwork.DoesNotExist:
        return render(request,'network/friendRequestList.html')

此时好友列表视图可简化为:

def friends(request, id):
    current_user = request.user
    friends = current_user.friends.all()
    context = {
        'friends': friends,
    }
    return render(request, 'friend_list.html', context)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 19:48:17