📝

Djangoのモデルでのフィールドルックアップ

2024/08/21に公開

DjangoのモデルでQuerySetのフィールドルックアップ

すぐに忘れてしまうので、モデルを利用したクエリ処理をを備忘録としてまとめておく

フィールドルックアップ

フィールドルックアップは、SQLのWHERE句の内容を指定する手段です。filter() 、 exclude() および get() にキーワード引数として指定します。

基本のルックアップキーワード引数は「カラム名__lookuptype=value」で指定します

ルックアップタイプ

以下のようなルックアップタイプがあります

キーワード 説明
exact 完全一致、アルファベットの大文字と小文字を区別する
iexact 完全一致、アルファベットの大文字と小文字を区別しない
contains 部分一致、アルファベットの大文字と小文字を区別する
icontains 部分一致、アルファベットの大文字と小文字を区別しない
startswith 前方一致、アルファベットの大文字と小文字を区別する
istartswith 前方一致、アルファベットの大文字と小文字を区別しない
endswith 後方一致、アルファベットの大文字と小文字を区別する
iendswith 後方一致、アルファベットの大文字と小文字を区別しない
in いずれかに一致、指定されたイテラブル(多くの場合、リスト、タプル、クエリセット)内に含まれるかをチェックします。あまり使われませんが、(イテラブルである)文字列は使用可能です
gt より大きい
gte 以上
lt より小さい
lte 以下
range 範囲のチェック(~~を含む)、range は SQL で BETWEEN が使えるところならどこでも使えます。日付、数字、そして文字でも使えます
regex 正規表現、アルファベットの大文字と小文字を区別する
iregex 正規表現、アルファベットの大文字と小文字を区別しない
isnull "True" または "False" を受け取り、それぞれ IS NULL と IS NOT NULL の SQL クエリに対応します
date datetimeフィールドの値を date としてキャストします。追加のフィールドルックアップを連結できます。date値を取ります
year 日付フィールドとdatetimeフィールドにおける、"年" の完全一致。追加のフィールドルックアップを連結できます。年を整数で指定します
month 日付フィールドおよびdatetimeフィールドにおける、"月" の完全一致。追加のフィールドルックアップを連結できます。1 (1月) から 12 (12月) までの整数を指定します
day 日付フィールドとdatetimeフィールドにおける、"日" の完全一致。追加のフィールドルックアップを連結できます。日を整数で指定します
week 日付フィールドおよびdatetimeフィールドにおける、 ISO-8601 に従った週番号 (1~52または53) を返します。すなわち、週は月曜日から始まり、最初の週にはその年の最初の木曜日が含まれます
week_day 日付フィールドとdatetimeフィールドにおける "曜日" の一致。追加のフィールドルックアップを連結できます。1 (日曜日) から 7 (土曜日) までの曜日を表す整数値を指定します
hour datetimeフィールドとtimeフィールドにおける、"時(hour)" の完全一致。追加のフィールドルックアップを連結できます。0 から 23 までの整数を指定します
minute datetime フィールドと time フィールドにおける、"分" の完全一致。追加のフィールドルックアップを連結できます。0 から 59 までの整数を指定します
second datetime および time フィールドにおける、"秒" の完全一致。追加のフィールドルックアップを連結できます。0 から 59 までの整数を指定します

exact

nameがFireDragonと完全一致

exactをつけなくても自動的にexactになる。デフォルトでexactと同じ意味になる

Monster.objects.filter(name__exact="FireDragon")
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`name` = 'FireDragon'

contains

nameにDragonが含まれる

含まれるかどうかの判定を行う

Monster.objects.filter(name__contains="Dragon")
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`name` LIKE BINARY '%Dragon%'

startswith

nameがDarkから始まる

前方一致を検索します

Monster.objects.filter(name__startswith="Dark")
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`name` LIKE BINARY 'Dark%'

endswith

nameがDragonで終わる

後方一致を検索します

Monster.objects.filter(name__endswith="Dragon")
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`name` LIKE BINARY '%Dragon'

in

いずれかに一致します。値にはイテラブル、つまり、リストなどを指定します。リスト、タプルなどが指定可能です。文字列も指定可能

リストに一致する

リストの要素に一致するデータを選択します。一致しないデータが含まれていてもOK

Monster.objects.filter(name__in=["FireDragon","Slime","XXX"])
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`name` IN ('FireDragon', 'Slime', 'XXX')

数値のリスト

Monster.objects.filter(hp__in=[40,60,80,100])
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`hp` IN (40, 60, 80, 100)

文字列で可能

利用パターンは少ないが文字列でも可能

Monster.objects.filter(name__in="abc")
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`name` IN ('a', 'b', 'c')

gt, gte

hpが40より大きい

Monster.objects.filter(hp__gt=40)
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`hp` > 40

lt, lte

mpが80より小さい

Monster.objects.filter(mp__lt=80)
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`mp` < 80

range

range は SQL で BETWEEN が使えるところならどこでも使えます。日付、数字、そして文字でも使えます。値をタプルで2個指定します

hpが40から80

 Monster.objects.filter(hp__range=(40,80))
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`hp` BETWEEN 40 AND 80

date

datetime フィールドの値を date としてキャストします。追加のフィールドルックアップを連結できます。 date 値を取ります

created_atが2020-08-10と等しい

datetimeフィールドに対して年月日を指定して検索します。一致したデータを取り出します。dateフィールドでは機能しない

# created_atはDatetime
import datetime
Monster.objects.filter(created_at__date=datetime.date(2020,8,10))
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    DATE(CONVERT_TZ(`monster`.`created_at`, 'UTC', 'Asia/Tokyo')) = '2020-08-10'

dateフィールドの場合、dateを利用しないで実現可能

# birthdayはDateフィールド
Monster.objects.filter(birthday=datetime.date(2000,5,12))

create_atが指定日より未来

dateとgteを併用して指定日より未来を検索します

Monster.objects.filter(created_at__date__gte=datetime.date(2021,4,1))
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    DATE(CONVERT_TZ(`monster`.`created_at`, 'UTC', 'Asia/Tokyo')) >= '2021-04-01'

year

日付フィールドとdatetimeフィールドにおける、"年" の完全一致。追加のフィールドルックアップを連結できます。年を整数で指定します

年が等しい

Monster.objects.filter(birthday__year=2001)
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    `monster`.`birthday`
BETWEEN
    '2001-01-01' AND '2001-12-31'

month

日付フィールドおよびdatetimeフィールドにおける、"月" の完全一致。追加のフィールドルックアップを連結できます。1 (1月) から 12 (12月) までの整数を指定します

月が等しい

Monster.objects.filter(birthday__month=5)
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    EXTRACT(MONTH FROM `monster`.`birthday`) = 5

day

日付フィールドおよびdatetimeフィールドにおける、 ISO-8601 に従った週番号 (1~52または53) を返します。すなわち、週は月曜日から始まり、最初の週にはその年の最初の木曜日が含まれます

日が等しい

Monster.objects.filter(birthday__day=20)
SELECT
    `monster`.`id`,
    `monster`.`name`,
    `monster`.`hp`,
    `monster`.`mp`,
    `monster`.`type`,
    `monster`.`birthday`
FROM
    `monster`
WHERE
    EXTRACT(DAY FROM `monster`.`birthday`) = 20

Discussion