djangoクエリセットでOR条件を実行する方法は?


294

次のSQLクエリに相当するDjangoクエリを記述したいと思います。

SELECT * from user where income >= 5000 or income is NULL.

Djangoクエリセットフィルターの作成方法

User.objects.filter(income__gte=5000, income=0)

これはANDフィルターなので、機能しません。私がしたいOR個々のクエリセットの和集合を取得するためのフィルタ。


回答:


547
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

ドキュメント経由


ORMとQueryの両方の出力を関連付けて理解できるように、object.queryの出力を追加すると役立ちます。ところで、素晴らしい例です。
Eddwin Paz 2017

このタイプのクエリを使用するか、2つの個別のクエリを実行する方が良いですか?
MHB

60

QuerySetはPython __or__演算子(|)、または共用体を実装しているため、機能します。ご想像のとおり、|2項演算子はQuerySetso order_by()、を返し、.distinct()他のクエリセットフィルターは最後まで追加できます。

combined_queryset = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
ordered_queryset = combined_queryset.order_by('-income')

アップデート2019-06-20:これはDjango 2.1 QuerySet APIリファレンスに完全に記載されています。より歴史的な議論はDjangoProjectチケット#21333にあります。


18
「文書化されていない」と「レガシー」は私を怖がらせます。ここで受け入れられた回答に詳述されているように、Qオブジェクトを使用する方が安全だと思います。
0atman

2
FYI、order_by()、distinct()は、パイプライン化された
クエリセット

@carruthdありがとう。私もこれを確認しました。編集
予定

order_by()を個々のクエリセットに適用して組み合わせることはできますか?各条件の順序が維持されるようにするには?たとえば、combined_queryset = User.objects.filter(income__gte = 5000).order_by( 'income')| User.objects.filter(income__lt = 5000).order_by( '-income')?
デッドロック

2
@オートマン:| 演算子が文書化されています。docs.djangoproject.com/en/2.0/ref/models/querysetsを参照してください: "一般に、Q()オブジェクトを使用すると、条件を定義して再利用できます。これにより、|(OR)および&( AND)演算子。特に、クエリセットでORを使用することはできません。」以前のバージョンのドキュメントをチェックしませんでしたが、パイプオペレーターは少なくともDjango 1.1.4で動作します(試してみただけです)。
makeroo 2018年

10

どちらのオプションも、既存の回答ですでに言及されています。

from django.db.models import Q
q1 = User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

そして

q2 = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)

ただし、どちらを優先するかについては、いくつかの混乱があるようです。

ポイントは、それらはSQLレベル同一であるため、好きなものを自由に選択してください!

DjangoのORMクックブックは、ここで、このことについていくつかの詳細に語っ関連する部分です。


queryset = User.objects.filter(
        first_name__startswith='R'
    ) | User.objects.filter(
    last_name__startswith='D'
)

につながる

In [5]: str(queryset.query)
Out[5]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

そして

qs = User.objects.filter(Q(first_name__startswith='R') | Q(last_name__startswith='D'))

につながる

In [9]: str(qs.query)
Out[9]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
 "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
  "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
  "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
  WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

ソース:django-orm-cookbook


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.