Home > Back-end >  How can I display the added Friends to their respective user friends list?
How can I display the added Friends to their respective user friends list?

Time:08-10

I am developing a feature same like Facebook. means a user can send a friend request and then that specific user will accept the friend request. so it means they both become friends with each other. Now how can I display them in such a way that user A is a friend of User B and vice versa? That's how I have developed it but can't display both of the users in the friend's list.

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)

Sending a friend request using the following method/logic:

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

Accepting a friend request using the following logic:

def acceptNetworkRequest(request, id):
    try:
        # if 'accept_friendRequest' in request.GET:
        friend_request = AddToNetwork.objects.get(id = id)
        print("\n Friend Request \n", friend_request)
        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')

Logic to display the friends in the respective profiles:

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,
        # 'approved': friend_to,
        # ' key' : value
    }
    return render(request, 'friend_list.html', context)

Now I want to use the model attribute add_to and added_from so that I can display the friends in their respective profiles. At the moment, either it displays a friend which uses the add_to attribute or added_from.

template for friends_list:

            {% for friend in friends %}
              <tr>
                <!-- <td scope="row">{{forloop.counter}}</td> -->
                <td>{{friend.add_to.first_name}} {{friend.add_to.last_name}}</td>
                <br>
               </tr>
             </tr>
            {% endfor %}

is there anyone who can guide me?

EDIT: my user model:

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)

CodePudding user response:

The way to get the list of friends from your current model would be something like this:

User.objects.filter(
    Q(add_from=user)& # get requests sent by the user
    Q(add_from__network_status='ACCEPT')| # must be accepted
    Q(add_to=user)&   # and those sent to the user
    Q(add_to__network_status='ACCEPT') # must be accepted
)

This should work fine but you might want another model that actually stores the friend lists, you may find it to be more concise and manageable. Something like storing friends as a m2m field on the user or having a FriendList model that stores the main user and their friends.

Edit - my code above is incorrect, the add_from field accesses the related AddToNetwork objects but then doesn't access the users related to those objects. It's necessary to add __add_to and __added_from respectively to get back to the user again.

get_user_model().objects.filter(
    Q(add_from__add_to=user)& # get requests sent by the user
    Q(add_from__network_status='ACCEPT')| # must be accepted
    Q(add_to__added_from=user)&   # and those sent to the user
    Q(add_to__network_status='ACCEPT') # must be accepted
)
  • Related