Помогите перевести этот запрос в Django ORM - PullRequest
1 голос
/ 30 июля 2011

У меня есть модель Дружбы с двумя связанными объектами пользователя, связанными с ней. Я хотел бы написать метод, который принимает пользователя и возвращает список друзей этого пользователя. Я делал это через:

 friends = Friendship.objects.filter(Q(user1=user) | Q(user2=user))
 friends_list = [f.user1 if user == f.user2 else f.user2 for f in friends]

но это влечет за собой запрос для каждого пользователя, который возвращается в наборе запросов (например, сотни запросов). Я мог бы написать это через:

 friends = Friendship.objects.select_related().filter(Q(user1=user) | Q(user2=user))
 friends_list = [f.user1 if user == f.user2 else f.user2 for f in friends]

но это делает ВНУТРЕННЕЕ СОЕДИНЕНИЕ для пользовательской таблицы. Я мог бы также написать это через пользовательский SQL,

 friends = User.objects.raw("""
            SELECT * FROM usertable WHERE id IN (SELECT
            user1_id FROM friendstable WHERE user2_id=%d) OR id IN 
            (SELECT user2_id FROM lists_friendship WHERE user1_id=%d);
            """ % (user.pk, user.pk))

но я думал, что должен быть способ сделать это внутри ORM без всех этих дополнительных поисков. Я пытался что-то сделать с id__in, но не смог найти способ получить идентификаторы пользователей из набора запросов друзей.

1 Ответ

0 голосов
/ 30 июля 2011

Предполагая, что вы настроили свою модель дружбы, как в примере ниже, и используете friend_set в качестве связанного имени поля from_friend в вашей модели, получение списка друзей пользователей может быть таким же простым, как и простое понимание списка.:

friends = [friendship.to_friend for friendship in user.friend_set.all()]

Это даже позволит вам получить доступ к друзьям пользователя в вашем шаблоне, не передавая его в качестве переменной:

{% for friendship in user.friend_set.all %}
    {{ friendship.to_friend.username }}
{% endfor %}

Ваша модель дружбы будет выглядеть так:

class Friendship(models.Model):
  from_friend = models.ForeignKey(
    User, related_name='friend_set'
  )
  to_friend = models.ForeignKey(
    User, related_name='to_friend_set'
  )
  def __unicode__(self):
    return u'%s, %s' % (
      self.from_friend.username,
      self.to_friend.username
    )
  class Meta:
    unique_together = (('to_friend', 'from_friend'), )

Вот отличная статья о создании сети друзей в Django: http://www.packtpub.com/article/building-friend-networks-with-django-1.0

Обратите внимание, что вам не нужно проверять и from_friend, и to_friend, чтобы получить друга пользователя.список.Если у вас есть модель дружбы по подписке / подписке, вам нужны только все экземпляры дружбы с пользователем from_friend =, а если у вас есть модель дружбы с двойным выбором, вы можете следить за тем, что делает Facebook, и добавить экземпляр для приглашенного друга как * 1017.* как только они примут приглашение друга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...