запрос ИЛИ условие базы данных django

#python #django #database #sqlite #django-models

Вопрос:

Я внедряю систему друзей, похожую на facebook, где можно отправлять запросы на дружбу и принимать запросы, а затем видеть своих друзей. На странице, где отображаются запросы на добавление в друзья, я пытаюсь отфильтровать пользователей, которые приняли запрос на добавление в друзья и уже являются друзьями. В приведенном ниже коде ‘u’ — это текущий зарегистрированный пользователь. Таблица дружбы содержит два поля, оба внешних ключа, пожалуйста, смотрите Ниже:

     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) amp; ~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'),)
 

Когда я использую запрос, который я написал вверху, используя Q (сложные запросы), а затем использую итератор, я получаю следующую ошибку:

 'Friendship' object has no attribute 'iterator'
 

Как я могу достичь того, что я намереваюсь сделать, используя модели / запросы django?

Ответ №1:

Вы должны использовать .filter(…) [Django-doc], а не .get(…) [Django-doc]: .get(…) извлекает один Friendship объект и выдает ошибку, если такого объекта нет или если их несколько. .filter(…) с другой стороны, вернет (возможно, пустой) набор запросов всех Friendship записей, которые удовлетворяют заданному предикату:

 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) amp; ~Q(sender=x)) 

Кроме того, нет смысла использовать Q(sender=x) : x является Friendship объектом, а не объектом пользователя. Вероятно, вы хотите проверить, является ли from_friend_id or to_friend_id u , и, таким образом, использовать другой для фильтрации. Что-то вроде:

 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) 

Комментарии:

1. также нужен ли здесь .iterator()? для x в already_friends: будет работать нормально

2. @aberkb: это зависит от количества записей, которые будут извлечены. Если это может быть огромным, лучше использовать .iterator() , поскольку это не приведет к исчерпанию памяти. Может быть лучше использовать .iterator() , если неизвестно, каким будет количество записей.