2012-04-03 9 views
6

Mam problem z uzyskaniem zapytania ORM Django, aby działał poprawnie. Mam ten model Przyjaźń:Zapytanie ORM Django dla znajomych użytkownika

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

aby znaleźć przyjaciół dla danego użytkownika, musimy sprawdzić user1 i Użytkownik2 ponieważ nigdy nie możemy być pewni, co strona relacji będą dalej. Tak, aby wszystkie przyjaciół dla danego użytkownika, używam następujące zapytanie:

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

Wydaje mi się, że powinna działać, ale tak nie jest. Daje mi duplikaty. Oto SQL, który generuje:

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')) 
); 

Oto SQL, że chcę, która produkuje poprawne wyniki:

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 

wiem, że mogę to zrobić w surowy zapytania, ale potem don Myślę, że będę mógł się połączyć. Czy istnieje ładny, czysty sposób na zrobienie tego bez wchodzenia na surowo?

Odpowiedz

1

Proste rozwiązanie:

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

ktoś wie żadnych wadę?

+0

Przetestowałem to i działa. Osobiście nie napisałbym tego zapytania dokładnie tak, jak ORM go wypluwa, ale wydaje się, że działa dość dobrze. Jedynym minusem są tutaj możliwe duplikaty przy użyciu pola w kolejności, która nie jest zawarta w zestawie wyników. – Dustin

3
+0

Musi przechowywać dodatkowe informacje, wydaje się, że to nie zadziała. – santiagobasulto

+0

@santiagobasulto lub określ [za pomocą tabeli] (https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany) dla M2M –

+0

Rozwiązanie dla rozwiązania @santiagobasulto działa dla mnie. Zastanawiam się jednak, czy to rozwiązanie może być nieco prostsze, a może nawet działać lepiej, o ile mogę jeszcze określić tabelę pośrednią. Jednak nie jest dla mnie jasne, jak to zrobić w symetrycznej relacji. Próbuję to rozgryźć teraz ... – Dustin

Powiązane problemy