2012-04-03 7 views
6

Ho problemi a ottenere una query ORG Django per funzionare correttamente. Ho questo modello Amicizia:Domanda ORMA di Django per gli amici di un utente

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

di trovare i tuoi amici per un determinato utente, dobbiamo controllare user1 e user2 perché non possiamo mai essere sicuri che parte della relazione che sarà on. Quindi, per ottenere tutti gli amici per un determinato utente, io uso la seguente query:

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

Questo mi sembra come dovrebbe funzionare, ma non è così. Mi dà dei duplicati. Ecco l'SQL che esso genera:

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

Ecco l'SQL che voglio, che produce risultati corretti:

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 

So che posso fare questo in una query crudo, ma poi ho don Penso che sarò in grado di catena. C'è un bel modo pulito per farlo senza andare crudo?

risposta

1

Soluzione semplice:

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

Qualcuno sa qualsiasi inconveniente?

+0

Ho provato questo e funziona. Personalmente non scriverò la query esattamente come l'ORM sta sputando fuori, ma sembra ancora funzionare ragionevolmente bene. L'unico lato negativo qui è i possibili duplicati utilizzando un campo in ordine per quello non è incluso nel set di risultati. – Dustin

3
+0

Ha bisogno di memorizzare ulteriori informazioni, sembra che non funzionerà. – santiagobasulto

+0

@santiagobasulto o specificare una [tramite tabella] (https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany) per M2M –

+0

La soluzione della soluzione @santiagobasulto funziona per me. Tuttavia, mi chiedo se questa soluzione potrebbe essere un po 'più semplice e forse anche funzionare meglio, purché possa ancora specificare una tabella. Tuttavia, non mi è chiaro come farlo in una relazione simmetrica. Sto cercando di capirlo adesso ... – Dustin

Problemi correlati