catBuddy
catBuddy

Reputation: 397

django database query OR condition

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?

Upvotes: 1

Views: 66

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476719

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)

Upvotes: 1

Related Questions