#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()
, если неизвестно, каким будет количество записей.