LoginSignup
6
4

【Django】filter/get/excludeで複数の条件指定やQuerySetを結合する方法

Last updated at Posted at 2021-10-08

単一の条件指定

通常このように指定していると思います。

views.py
#QuerySetで返す
MyUser.objects.filter(name=query)

#ひとつだけ返す(確実にデータがある場合にのみgetは使う)
MyUser.objects.get(name=query)

#除外する
MyUser.objects.all().exclude(name=query)

複数の条件指定

andの場合

複数の条件全てを満たすものを取得する場合,を使います。

views.py
#名前にtaroを含む20歳のユーザーを取得
MyUser.objects.filter(name__icontains="taro", age="20")

#名前がtaroで20歳のユーザーを取得
MyUser.objects.get(name="taro", age="20")

#名前にtaroを含む20歳のユーザーを除外
MyUser.objects.all().exclude(name__icontains="taro", age="20")

orの場合

条件を一つでも満たすものを取得する場合Q objects|を使います。

views.py
from django.db.models import Q

#名前にtaroを含むか、20歳以下のユーザーを取得
MyUser.objects.filter( Q(name__icontains="taro")|Q(age__lte="20") )

#名前にtaroを含むか、20歳以下のユーザーを除外
MyUser.objects.all().exclude( Q(name__icontains="taro")|Q(age__lte="20") )

上記の場合、taroを含む全てのユーザーと、20歳以下の全てのユーザーが取得できます。

andとor両方使う場合

Q objectsキーワード引数を混在させる場合は、先にQ objectsを書くこと。

views.py
from django.db.models import Q

#Tokyo出身で、名前にtaroを含むか、20歳以下のユーザーを取得
MyUser.objects.filter(
    Q(birthplace="Tokyo"), Q(name__icontains="taro")|Q(age__lte="20"))

#キーワード引数を使う場合
MyUser.objects.filter(
    Q(name__icontains="taro")|Q(age__lte="20"), birthplace="Tokyo",)

#これだと無効になる
MyUser.objects.filter(
    birthplace="Tokyo", Q(name__icontains="taro")|Q(age__lte="20"))

全てQ objectsにすれば順番は気にしないでOK!

先にキーワード引数を書くと無効になるので注意!

複数のQuerySetを結合する

複数のQuerySetを結合したい場合は|を使う。

views.py
hoge1 = MyUser.objects.filter(hogehoge1)
hoge2 = MyUser.objects.filter(hogehoge2)

#hoge1と2のQuerySetを結合する
total_hoge = hoge1|hoge2

#QuerySetから本人を除外する
total_hoge = (hoge1|hoge2).exclude(id=request.user.id)

#重複を無くす(※注意)
total_hoge = (hoge1|hoge2).distinct()

重複についてshellで確認したところ、hoge1|hoge2の時点で重複が無くります。

なので、クエリが複数のテーブルにまたがっている場合など、何らかの理由で重複が発生した場合以外は使わないでOK!

というのも・・

distinctは注意

データベースの種類やorder.byの有無で機能しない場合があります。

PostgreSQLとそれ以外で書き方が変わります。

詳しくは公式ページで確認してみてくださいまし!

演算子で結合

この方法は重複等色々手間が発生するで、上記の|をオススメしますが一応紹介。

views.py
hoge1 = MyUser.objects.filter(hogehoge1)
hoge2 = MyUser.objects.filter(hogehoge2)

#hoge1と2のリスト化して結合する
total_hoge = list(hoge1) + list(hoge2)

#.excludeは使えないので結合する前に除外しておく
hoge1 = MyUser.objects.filter(hogehoge1).exclude(id=request.user.id)
hoge2 = MyUser.objects.filter(hogehoge2).exclude(id=request.user.id)
#本人を除外した
total_hoge = list(hoge1) + list(hoge2)

いや、もう演算子を使うのは色々と不便なので却下ですね笑

ちょっと助長でしたがこんな感じです!

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4