ユーニックス総合研究所

  • home
  • archives
  • django-filter

DjangoのModel.objects.filter()の使い方【QuerySet】

  • 作成日: 2020-11-27
  • 更新日: 2023-12-24
  • カテゴリ: Python

Djangoのfilter()の使い方

PythonのWebフレームワークである「Django(ジャンゴ)」には、オブジェクトを取得するためのメソッドがいくつかあります。
Model.objects.filter()はその中の1つで、これは取得したオブジェクトをフィルタリングするのに使われます。

オブジェクトの取得の条件を絞り、結果を厳選するのに使います。

この記事では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オブジェクトでラップされるのがわかります。
つまりfilterQオブジェクトを使ったコードのエイリアスだということになります。

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モデルのnameageフィールドをfilter()に指定する場合は↓のように書くことが出来ます。

taro = Person.objects.filter(name='太郎', age=20).first()  

print(taro.name, taro.age)  

↑のfilter()だとname太郎でかつage20Personオブジェクトにヒットします。
↑の出力結果↓。

太郎 20  

OR検索

ちなみにfilter()OR検索するにはdjango.db.models.Qクラスを使う必要があります。
↓の例ではname太郎またはage20Personオブジェクトにヒットさせています。
この条件だと複数のオブジェクトにヒットする可能性があるため、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)  

↑の出力結果↓。

太郎  
太郎  

部分一致

Personnameに部分一致させたい場合はcontainsを使います。
これはフィールド名と組み合わせて使います。
たとえばnameに「」を部分一致させたい場合は↓のようにします。

persons = Person.objects.filter(name__contains='郎').all()  

for person in persons:  
    print(person.name)  

↑の出力結果↓。

太郎  
太郎  
次郎  
三郎  

おわりに

Model.objects.filter()の使い方を解説しました。
filter()にはこの他にもいろいろな使い方があるので、ぜひ調べてみてください。

🦝 < フィルタリングでみんな幸せ