DjangoのModel.objects.filter()の使い方【QuerySet】
- 作成日: 2020-11-27
- 更新日: 2023-12-24
- カテゴリ: Python
Djangoのfilter()の使い方
PythonのWebフレームワークである「Django(ジャンゴ)」には、オブジェクトを取得するためのメソッドがいくつかあります。
Model.objects.filter()
はその中の1つで、これは取得したオブジェクトをフィルタリングするのに使われます。
オブジェクトの取得の条件を絞り、結果を厳選するのに使います。
- Django documentation | Django documentation | Django
- filter() - QuerySet API reference | Django documentation | Django
この記事ではModel.objects.filter()
の使い方について解説します。
filter()
を使うことで柔軟なオブジェクトの絞り込み検索が可能になります。
検索フォームなどの実装では必須になるメソッドです。
解説用のモデルの作成
この記事ではfilter()
の解説のために簡単なモデルを作成します。
モデル名はPerson
で人物を表すモデルです。
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=64, help_text='名前')
age = models.IntegerField(help_text='年齢')
このモデルはname
, age
フィールドを持っています。
name
は人物の名前を表し、age
は年齢を表しています。
本記事の解説は↑のPerson
モデルのオブジェクトを↓のように初期化している前提です。
Person.objects.create(name='太郎', age=20)
Person.objects.create(name='太郎', age=50)
Person.objects.create(name='花子', age=30)
Person.objects.create(name='次郎', age=16)
Person.objects.create(name='三郎', age=40)
Model.objects.filter()の構造
Model.objects.filter()
はdjango.query
モジュールに定義されています。
filter()
はQuerySet
というクラスのメソッドです。
↓がfilter()
のコード全文です。
def filter(self, *args, **kwargs):
"""
Return a new QuerySet instance with the args ANDed to the existing
set.
"""
self._not_support_combined_queries('filter')
return self._filter_or_exclude(False, args, kwargs)
filter()
は可変長引数とキーワード引数を取るメソッドです。
返り値は新しく生成されたQuerySet
です。
コードを追いかけるとfilter()
の引数は↓のように最終的にQ
オブジェクトでラップされるのがわかります。
つまりfilter
はQ
オブジェクトを使ったコードのエイリアスだということになります。
def _filter_or_exclude_inplace(self, negate, args, kwargs):
if negate:
self._query.add_q(~Q(*args, **kwargs))
else:
self._query.add_q(Q(*args, **kwargs))
Model.objects.filter()の返り値
Model.objects
以下のメソッドの多くは返り値としてdjango.db.models.query.QuerySet
を返します。
filter()
もそういったメソッドのうちの1つです。
↓のようにfilter()
を単体で呼び出し、その返り値のタイプを出力します。
queryset = Person.objects.filter()
print(type(queryset))
結果は↓のような出力になります。
<class 'django.db.models.query.QuerySet'>
QuerySet
クラスにはfilter()
の他にもall()
やfirst()
などいろいろなメソッドがあります。
これらをドットでつなげて呼び出すことが出来るのがModel.objects
以下のメソッドの特徴です。
Model.objects.filter()の基本的な使い方
filter()
の基本的な使い方を解説します。
filter()
はオブジェクトの取得のさいに、検索結果をフィルタリングするために使われます。
たとえばall()
というメソッドを使うとDB内のオブジェクトをすべて取得することが出来ます。
persons = Person.objects.all()
しかし、特定の条件にマッチするオブジェクトや、特定の条件にマッチしないオブジェクトを取得したい場合、↑のコードを書いてから自力でフィルタリングするのは非効率的です。
DBへの問い合わせでそういったことができたほうが結果として処理速度は向上します。
そういう時にこのfilter()
というメソッドを使います。
たとえばPerson
オブジェクトのname
フィールドに「太郎
」という文字列をマッチさせたい場合は↓のように書きます。
queryset = Person.objects.filter(name='太郎')
この段階ではname
に太郎
が保存されているオブジェクトが複数ヒットしている状態です。
さらにfilter()
から返ってきたQuerySet
のメソッドfirst()
を使い、最初にヒットした太郎
のみ抽出します。
taro = Person.objects.filter(name='太郎').first()
print(taro.name)
↑の出力結果↓。
太郎
あるいはすべての太郎
を取得したい場合はall()
を使います。
taros = Person.objects.filter(name='太郎').all()
for taro in taros:
print(taro.name, taro.age)
↑の出力結果↓。
太郎 20
太郎 50
AND検索
filter()
に複数のフィールドを指定すると、結果はAND
検索になります。
たとえばPerson
モデルのname
とage
フィールドをfilter()
に指定する場合は↓のように書くことが出来ます。
taro = Person.objects.filter(name='太郎', age=20).first()
print(taro.name, taro.age)
↑のfilter()
だとname
が太郎
でかつage
が20
のPerson
オブジェクトにヒットします。
↑の出力結果↓。
太郎 20
OR検索
ちなみにfilter()
でOR
検索するにはdjango.db.models.Q
クラスを使う必要があります。
↓の例ではname
が太郎
またはage
が20
のPerson
オブジェクトにヒットさせています。
この条件だと複数のオブジェクトにヒットする可能性があるため、filter()
とall()
を使います。
from django.db.models import Q
persons = Person.objects.filter(Q(name='太郎') | Q(age=20)).all()
for person in persons:
print(person.name)
↑の出力結果↓。
太郎
太郎
部分一致
Person
のname
に部分一致させたい場合はcontains
を使います。
これはフィールド名と組み合わせて使います。
たとえばname
に「郎
」を部分一致させたい場合は↓のようにします。
persons = Person.objects.filter(name__contains='郎').all()
for person in persons:
print(person.name)
↑の出力結果↓。
太郎
太郎
次郎
三郎
おわりに
Model.objects.filter()
の使い方を解説しました。
filter()
にはこの他にもいろいろな使い方があるので、ぜひ調べてみてください。
🦝 < フィルタリングでみんな幸せ