2012-04-03 8 views
6

Django ORMクエリを正しく実行するのに問題があります。我々は、彼らが上になる関係のどのような側面を確認することはできませんので、我々はuser1とuser2のを確認する必要があり、特定のユーザーのために友人を見つけるためにユーザーの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',) 

:私はこの友情のモデルを持っています。したがって、特定のユーザーのすべての友人を取得するには、次のクエリを使用します。

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

これはうまくいくはずですが、そうではありません。それは私に重複を与える。ここではそれが生成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 

、その後私ドン:ここ

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、あります私は連鎖できると思う。生まれることなくこれを行うきれいな方法がありますか?

答えて

1

シンプルなソリューションを使用する必要があります

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

誰でも任意の欠点を知っているの?

+0

私はこれをテストして動作します。個人的には、ORMが吐き出すように正確にクエリを書いてはいませんが、依然として合理的にうまくいくようです。ここでの唯一の欠点は、結果セットに含まれていない順序でフィールドを使用することによって可能な重複があることです。 – Dustin

3
+0

余分な情報を保存する必要があるため、動作しないようです。 – santiagobasulto

+0

@santiagobasultoまたはM2M –

+0

の[through table](https://docs.djangoproject.com/ja/dev/topics/db/models/#intermediary-manytomany)を指定してください。@ santiagobasultoソリューションのソリューションが私に役立ちます。しかし、私がまだスルー・テーブルを指定できる限り、このソリューションがもう少しシンプルで、おそらくもっとうまくいくかどうかは疑問です。しかし、対称的な関係でそれをどうやって行うのかは分かりません。私は今それを理解しようとしています... – Dustin