I am implementing a friend system similar to facebook where one can send friendship requests and accept requests and then see their friends. On the page where one sees the friend requests I am trying to filter out the users who have accepted the friend request and are friend already now. In the code below, 'u' is the current logged in user. Friendship table hold two fields , both foreign keys, please see below:
try:
already_friends = Friendship.objects.get(Q(from_friend=u) | Q(to_friend=u))
for x in already_friends.iterator():
my_requests = FriendRequest.objects.filter(Q(receiver=request.user) & ~Q(sender=x))
except ObjectDoesNotExist:
class FriendRequest(models.Model):
sender = models.ForeignKey(User, related_name='the_sender',on_delete=models.CASCADE)
receiver = models.ForeignKey(User, related_name='the_receiver', on_delete=models.CASCADE)
def __str__(self):
return "request sent"
class Meta:
unique_together = (('sender', 'receiver'),)
class Friendship(models.Model):
from_friend = models.ForeignKey(User, related_name="from_friend", on_delete=models.CASCADE)
to_friend= models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return "Friend request accepted"
class Meta:
unique_together = (('from_friend', 'to_friend'),)
When I use the query I wrote at the top using Q (complex queries) and then use iterator, I get the following error:
'Friendship' object has no attribute 'iterator'
How can I achieve what I intend to do using django models/queries?
CodePudding user response:
You should use .filter(…)
[Django-doc] not .get(…)
[Django-doc]: .get(…)
retrieves a single Friendship
object, and will raise an error if there is no such object, or if there are multiple ones. .filter(…)
on the other hand will return a (possibly empty) queryset of all Friendship
records that satisfy the given predicate:
already_friends = Friendship.objects.filter(Q(from_friend=u) | Q(to_friend=u))
for x in already_friends.iterator():
my_requests = FriendRequest.objects.filter(Q(receiver=request.user) & ~Q(sender=x))
Furthermore it makes no sense to use Q(sender=x)
: x
is a Friendship
object, not a user object. You probably want to check if the from_friend_id
or to_friend_id
is the u
, and thus use the other one to filter. Something like:
already_friends = Friendship.objects.filter(Q(from_friend=u) | Q(to_friend=u))
for x in already_friends.iterator():
if x.from_user_id = u.id:
my_requests = FriendRequest.objects.filter(receiver=request.user, sender_id=x.to_user_id)
else:
my_requests = FriendRequest.objects.filter(receiver=request.user, sender_id=x.from_user_id)