【Django】データベース操作:条件指定でデータを検索(抽出)する方法
2021.10.12 /
本記事ではDjangoのデータベース操作における、細かい条件指定で目的のデータを検索(抽出)する方法について解説していきます。
データベースから目的のデータを検索する方法として、filter()メソッドやget()メソッド、exclude()メソッドなどがあり、これらの引数に条件を指定することで目的のデータを抽出できます。
引数に指定する検索条件には、ただ検索したい文字列を指定するだけでなく、特別な手法で検索条件を指定することもできます。
ここではフィールドルックアップを使った条件指定で、データを検索する方法を解説していきます。
条件指定でデータを検索(抽出)とは
Djangoではデータベース操作にORM(Object-Relational Mapping)という技法を使っています。
これによりモデルクラスを利用したデータベース操作が可能になります。
Djangoによる基本的なデータベース操作(取得・作成・更新・削除)については以下記事をご参照ください。
【Django】データベース操作(取得・作成・更新・削除):ORMの利用
データベースから特定のデータを検索(抽出)するためには、filter()メソッドやget()メソッド、exclude()メソッドといったメソッドを使用します。
これらのメソッドは引数に検索する条件を指定する必要があります。
メソッドの引数に指定する検索条件をうまく利用することで、目的に合ったデータを正確に取得できるようになります。
「データベース操作(取得・作成・更新・削除):ORMの利用」で紹介した方法以外にフィールドルックアップを利用した検索条件を指定する方法があります。
フィールドルックアップによる検索
フィールドルックアップとは、検索条件を指定するための技法です。
SQLでいうWHERE句の内容を指定しています。
各メソッドの引数に次の構文の形を取ります。
field__lookuptype=value
fieldには検索条件で利用するモデルが持つフィールド名(列名)を指定し、lookuptypeとの間にはアンダーバーが2つ連続します。
例えばモデルMemberのフィールドfirst_nameで“O”から始まるデータを抽出したい場合は次のように記述します。
>>> Member.objects.filter(first_name__startwith='O')
無効な引数を指定した場合はTypeErrorが発生します。
次に利用頻度が多いフィールドルックアップについて解説していきます。
文字列の一致
exact:完全な一致
指定した文字列と完全に一致するデータを抽出する場合は、exactを使用します。
モデル名.objects.メソッド(フィールド__exact="条件")
例えばモデルMemberのフィールドaddressで“Japan”のデータを抽出したい場合は次のように記述します。
>>> Member.objects.get(address__exact="Japan")
次のコードも上記のコードと同様の結果を返します。
>>> Member.objects.get(address="Japan")
つまりlookuptypeを指定せずに検索した場合、__exactを指定したと見なされるのです。
これはlookuptypeの中で最もexactの使用頻度が高いことから、このような設定になっています。
上記をSQLで表すと次のようになります。
SELECT ... WHERE address = 'Japan';
iexact:完全な一致(大文字小文字の区別なし)
指定した文字列と完全に一致(大文字小文字の区別なし)するデータを抽出する場合は、iexactを使用します。
モデル名.objects.メソッド(フィールド__iexact="条件")
>>> Member.objects.get(address__iexact="japan")
上記の条件では、“Japan”や“JAPAN”でも検索にヒットします。
上記をSQLで表すと次のようになります。
SELECT ... WHERE address ILIKE 'japan';
contains:部分的な一致
指定した文字列と部分的に一致するデータを抽出する場合は、containsを使用します。
モデル名.objects.メソッド(フィールド__contains="条件")
>>> Member.objects.get(address__contains ="Japan")
上記をSQLで表すと次のようになります。
SELECT ... WHERE address LIKE '%Japan%';
大文字と小文字の区別をなくす場合は、icontainsを使用します。
in:複数条件のいずれかと一致
exactでは一つの条件しか指定することができません。リスト内のいずれかの条件と一致するデータを取得したい場合は、inを使用します。
モデル名.objects.メソッド(フィールド__in=[リストデータ])
>>> Member.objects.get(address__in=["Japan", "US", "Canada"])
上記の条件では、addressがJapanかUS、Canadaのいずれかであれば取得されます。
取得したい要素をリスト化すれば一回ですべて検索できるため、使い勝手の良いルックアップタイプの一つです。
上記をSQLで表すと次のようになります。
SELECT ... WHERE address IN (“Japan”, “US”, “Canada”);
startwith:前方一致
指定した文字列と前方一致するデータを抽出する場合は、startwithを使用します。
モデル名.objects.メソッド(フィールド__startwith="条件")
>>> Member.objects.get(address__startwith ="Japan")
上記をSQLで表すと次のようになります。
SELECT ... WHERE address LIKE 'Japan%';
大文字と小文字の区別をなくす場合は、istartwithを使用します。
endwith:後方一致
指定した文字列と後方一致するデータを抽出する場合は、endwithを使用します。
モデル名.objects.メソッド(フィールド__endwith="条件")
>>> Member.objects.get(address__endwith ="Japan")
上記をSQLで表すと次のようになります。
SELECT ... WHERE address LIKE '%Japan';
大文字と小文字の区別をなくす場合は、iendwithを使用します。
数値による大小の比較
gt:より大きい
指定した値よりも大きいデータを抽出する場合は、gt(greater than)を使用します。
モデル名.objects.メソッド(フィールド__gt="条件")
>>> Member.objects.get(age__gt=54)
# ageが54より大きい、 age > 54
gte:以上
指定した値よりも大きいまたは等しいデータを抽出する場合は、gte(greater than or equal to)を使用します。
モデル名.objects.メソッド(フィールド__gte="条件")
>>> Member.objects.get(age__gte=54)
# ageが54以上、 age >= 54
lt:より小さい
指定した値よりも小さいデータを抽出する場合は、lt(less than)を使用します。
モデル名.objects.メソッド(フィールド__lt="条件")
>>> Member.objects.get(age__lt=54)
# ageが54より小さい、 age < 54
lte:以下
指定した値よりも小さいまたは等しいデータを抽出する場合は、lte(less than or equal to)を使用します。
モデル名.objects.メソッド(フィールド__lte="条件")
>>> Member.objects.get(age__lte=54)
# ageが54以下、 age <= 54
範囲指定による検索
日時や時間、数値の範囲を指定して検索を行いたい場合は、rangeを使用します。
モデル名.objects.メソッド(フィールド__range=(start, end))
>>> Member.objects.get(age__range=(20, 54))
上記をSQLで表すと次のようになります。
SELECT ... WHERE age between “20” and “54”;
日付で範囲指定したい場合は、次のようにコードを書きます。
import datetime
start_date = datetime.date(2021, 5, 4)
end_date = datetime.date(2021, 10, 12)
Member.objects.filter(pub_date__range=(start_date, end_date))
まとめ
本記事「【Django】データベース操作:条件指定でデータを検索(抽出)する方法」はいかがでしたか。
フィールドルックアップが使いこなせるようになると、データベースの検索が非常に楽になります。
ぜひフィールドルックアップをご自身のWebアプリケーションで利用してみてください。