2013-03-25 12 views
8

私はDjangoの組み込みユーザーモデルを使用しており、ユーザーにはForeignKeyを持つカスタムFooオブジェクトを持っています。私はジャンゴでこれを実現する必要がありますどのようにDjangoはフィルター付きの外部結合を残しました

SELECT * from auth_user LEFT OUTER JOIN "foo" ON 
(auth_user.id = foo.id AND <other criteria here>) 

:私は、すべてのユーザーオブジェクトとそのような特定の制約に合うのFooオブジェクトのすべてを選択していますよ?これまで私が試してみた:

User.objects.filter(foo__<criteria>) 

が、それは次のようにSQLを生成:

SELECT * from auth_user LEFT OUTER JOIN "foo" ON 
(auth_user.id = foo.id) WHERE <other criteria here> 

をし、唯一の基準に合うのFooオブジェクトを持っているユーザーオブジェクトを返します。あるいは、私はすべてのUserオブジェクトを選択し、それぞれのオブジェクトに対してクエリを実行できますが、それは実質的に効率が悪いでしょう。

+0

他の基準は何ですか?それはまだ 'Foo'モデルに関係していますか? – Ngenator

+0

はい。 Fooにはいくつかの日付フィールドがあり、指定した日付範囲からFoosだけを選択しています。 – Phobophobia

+0

'User.objects.filter(foo__ )'とは何ですか? 'foo'は' User'モデルのフィールドではありません。私は 'LEFT OUTER JOIN'を持つクエリを生成することはできませんでした。 – user2233706

答えて

1

あなたはDjangoが、あなたがselect_related()を使用したい、ユーザーオブジェクトに関連するすべてのUserオブジェクトとすべてのFooオブジェクトを取得したい場合:

User.objects.all().select_related('foo') 

が、ここであなたがすべてを望んでいませんFooオブジェクトに関連するオブジェクトは、条件を満たすサブセットのみを必要とします。私はDjangoに単一のクエリセットでそれを行うよう指示する方法は知らない。しかし、あなたんが、個別に選択して、Pythonで参加するか、両方行うことです行うことができます

# Map from user id to corresponding Foo satisfying <criteria>, if any. 
foos = {foo.user_id: foo for foo in 
     Foo.objects.filter(user__isnull = False, <criteria>)} 
for user in User.objects.all(): 
    foo = foos.get(user.id) 
    # ... 

(これは、任意のより多くのデータベース作業を行うか、それ以上のデータを転送するあなたのLEFT OUTER JOINは希望よりも、私は考えていないがそれは合理的なアプローチです)

+0

パーフェクト、ありがとう:) – Phobophobia

+1

あなたのモデルがどのように関連しているかは実際にはわかりませんので、ニーズに合わせて提案したソリューションを調整する必要があるかもしれません。 –

+0

あなたのソリューションは次のクエリを実行します:SELECT•••FROM "auth_user" WHERE "auth_user"。 "id" = Fooが条件を満たすすべてのユーザー。私が知る限り、これは "{foo.user_id:foo";いずれかの部分を他の部分に置き換えると、クエリが実行されなくなります。 2つのモデルの間の唯一の関係は、FooにUserを指すForeignKeyがあることです。 – Phobophobia

1

それは不格好だが、これはそれを行う必要があります。

User.objects.raw('SELECT auth_user.* from auth_user LEFT OUTER JOIN ' 
       '"foo" ON (auth_user.id = foo.id AND ' 
       '<other criteria here>)') 

あなたは選択の左側にそれらを追加することにより、返されたユーザオブジェクト上の余分な属性をスプラットすることができます。

0

あなたが行くことができるLEFT OUTER JOINを取得するには:

User.objects.select_related('foo').filter(Q(foo__isnull=True) | Q(<other criteria here>)) 

DjangoはLEFT OUTER JOINを生成することを指示するためにfoo__isnull=Trueを使用しています。 foo__isnull=Falseを与えると、フィルタパラメータなしでINNER JOINが生成されます。

関連する問題