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
)