14

Djangoの組み込みユーザーモデルを使用していて、ForeignKeytoUserを持つカスタムFooオブジェクトがあります。次のように、特定の制約に適合するすべてのUserオブジェクトとすべてのFooオブジェクトを選択しようとしています。

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

Djangoでこれをどのように達成する必要がありますか?これまでに試しました:

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オブジェクトのみを返します。または、すべてのユーザーオブジェクトを選択して、それぞれに対してクエリを実行することもできますが、それでは効率が大幅に低下します。

4

5 に答える 5

16

あなたLEFT OUTER JOINが行くことができます:

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

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

于 2018-01-19T02:21:15.293 に答える
5

Django 2.0はFilteredRelationオブジェクトLEFT OUTER JOINを導入しました。これは、次のようなコードで言及したクエリをほぼ正確に生成できます。

User.objects.annotate(
    filtered_foo=FilteredRelation('foo', condition=Q(foo_<criteria>))
).values(...) # e.g. 'user__id', 'filtered_foo__id'

filtered_fooただし、で指定するvaluesか、追加のアノテーションを使用して、使用するフィールドを明示的に要求する必要があるようです。または、ユーザーによってグループ化されたフィールドを集計することもできfiltered_fooます。

于 2020-09-22T14:25:03.397 に答える
0

Djangoですべてのオブジェクトとユーザーオブジェクトに関連するUserすべてのオブジェクトをフェッチする場合は、次を使用します。Fooselect_related()

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。したがって、これは合理的なアプローチだと思います。)

于 2013-03-25T20:46:25.900 に答える
0

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

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

選択範囲の左側に追加することで、返されたUserオブジェクトに追加の属性を追加できます。

于 2015-09-15T13:46:12.500 に答える
0

自分のニーズを満たすかもしれない良い答えがありますが、ベストプラクティスは

from django.db.models import Prefetch


User.objects.all().prefetch_related(Prefetch(<related_name>, queryset=Foo.objects.filter(<criteria>)))

<related_name> ='foo' if:

class Foo(models.Model):
    user = models.ForeignKey(User, related_name='foo')

これにより、指定されたフィルター基準を持つユーザーに関連するすべてのユーザーとfooオブジェクトが返されます。

于 2021-02-04T21:09:19.797 に答える