Запрос Django ORM для друзей пользователя - PullRequest
6 голосов
/ 03 апреля 2012

У меня проблемы с получением правильной работы запроса Django ORM.У меня есть эта модель дружбы:

class Friendship(models.Model):
    user1 = models.ForeignKey(User, related_name='friendships1')
    user2 = models.ForeignKey(User, related_name='friendships2')
    class Meta:
        unique_together = ('user1', 'user2',)

Чтобы найти друзей для данного пользователя, мы должны проверить user1 и user2, потому что мы никогда не можем быть уверены, на какой стороне отношений они будут.Итак, чтобы получить всех друзей для данного пользователя, я использую следующий запрос:

user = request.user
User.objects.filter(
    Q(friendships1__user2=user, friendships1__status__in=statuses) |
    Q(friendships2__user1=user, friendships2__status__in=statuses)
)

Мне кажется, это должно работать, но это не так.Это дает мне дубликаты.Вот SQL, который он генерирует:

SELECT auth_user.*
FROM auth_user
LEFT OUTER JOIN profile_friendship ON (auth_user.id = profile_friendship.user1_id)
LEFT OUTER JOIN profile_friendship T4 ON (auth_user.id = T4.user2_id)
WHERE (
    (profile_friendship.status IN ('Accepted') AND profile_friendship.user2_id = 1 )
    OR (T4.user1_id = 1 AND T4.status IN ('Accepted'))
);

Вот SQL, который я хочу, который дает правильные результаты:

SELECT f1.id as f1id, f2.id AS f2id, u.*
FROM auth_user u
LEFT OUTER JOIN profile_friendship f1 ON (u.id = f1.user1_id AND f1.user2_id = 1 AND f1.status IN ('Accepted'))
LEFT OUTER JOIN profile_friendship f2 ON (u.id = f2.user2_id AND f2.user1_id = 1 AND f2.status IN ('Accepted'))
WHERE f1.id IS NOT NULL OR f2.id IS NOT NULL

Я знаю, что я могу сделать это в необработанном запросе,но тогда я не думаю, что смогу зацепиться.Есть ли хороший чистый способ сделать это без сырых?

Ответы [ 2 ]

3 голосов
/ 03 апреля 2012

Вы должны использовать ManyToManyField.symmetrical

https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.symmetrical

1 голос
/ 04 апреля 2012

Простое решение:

user = request.user
User.objects.filter(
    Q(friendships1__user2=user, friendships1__status__in=statuses) |
    Q(friendships2__user1=user, friendships2__status__in=statuses)
).distinct()

Кто-нибудь знает какой-нибудь недостаток?

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