Home > other >  django database query OR condition
django database query OR condition

Time:10-31

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)
  • Related