ユーニックス総合研究所

  • home
  • archives
  • django-q

DjangoのQオブジェクトの使い方: OR検索、否定

  • 作成日: 2021-12-08
  • 更新日: 2023-12-25
  • カテゴリ: Django

DjangoのQオブジェクトの使い方

Djangoではfilter()でDBのレコードを検索することができます。
その時にOR検索や否定条件を指定したい時があります。
そういう時はQオブジェクトを使うと簡単にできます

この記事ではDjangoのQオブジェクトについて具体的に解説します。
具体的には↓の項目を見ていきます。

  • Qオブジェクトのインポート方法
  • 普通に検索
  • OR検索
  • AND検索
  • 否定

関連記事

低スペックサーバーでDjangoとuWSGIを動かす時の設定
adminサイトにモデルを追加する【Django】
Django入門: 簡単な一行掲示板アプリを作る その1【Windows10】
Django入門: 管理サイト ~ 簡単な一行掲示板アプリを作る その11【Windows10】
Django入門: 微調整 ~ 簡単な一行掲示板アプリを作る その15【Windows10】

前提とするプロジェクト構造

今回の解説に使用するプロジェクトは↓のようなモデルを持ちます。

from django.db import models  


class Article(models.Model):  
    title = models.CharField(max_length=255, help_text='記事のタイトル')  
    content = models.TextField(max_length=4096, help_text='記事の内容')  

Articleという記事を表現するモデルを定義しています。
Articletitlecontentというフィールドを持ちます。
titleには記事のタイトル、contentには記事の内容が保存されます。

それからDBは↓のスクリプトで初期化している前提です。

from myapp.models import Article  

for a in Article.objects.all():  
    a.delete()  

Article.objects.create(title='鳥になりたい', content='')  
Article.objects.create(title='猫の額ほど狭い', content='')  
Article.objects.create(title='犬になりたい', content='')  
Article.objects.create(title='犬も歩けば棒に当たる', content='')  
$ python manage.py shell < init.py  

検証するDBには合わせて4レコードが挿入されています。
それぞれ鳥や猫、犬などのワードをtitleに含みます。

Qオブジェクトのインポート方法

Qオブジェクトをインポートするには↓のコードを書きます。

from django.db.models import Q  

Qオブジェクト自体はquery_utils.pyというモジュールに定義されています。

query_utils - Django

QオブジェクトはNodeを継承したオブジェクトで、Nodeの持つメソッド(add)も合わせて使うことができます。

普通に検索

QオブジェクトをORもANDも行わずに普通に使う方法です。
↓のようにQオブジェクトをフィルターに渡します。

    # 普通に使う  
    articles = Article.objects.filter(Q(title__icontains='鳥')).all()  
    print([a.title for a in articles])  
    # ['鳥になりたい']  

Qオブジェクトの引数にはfilter()検索条件と同様のパラメーターを指定します。
↑の場合はtitle__icontainsを指定しています。
これはArticletitleに「鳥」が含まれているか? という条件になります。

Qオブジェクトを渡したfilter()はQオブジェクトの条件でDBを検索します。
↑の場合だと「鳥になりたい」というtitleを持つレコードがヒットしています。

OR検索

QオブジェクトでOR検索する方法です
Qオブジェクトを「|」で繋げるとOR検索になります。
あるいはadd()に「Q.OR」を渡しても同様です。

    # OR検索  
    articles = Article.objects.filter(  
        Q(title__icontains='鳥') | Q(title__icontains='猫')  
    ).all()  
    print([a.title for a in articles])  
    # ['鳥になりたい', '猫の額ほど狭い']  

    # OR検索 その2  
    q = Q()  
    q.add(Q(title__icontains='鳥'), Q.OR)  
    q.add(Q(title__icontains='猫'), Q.OR)  

    articles = Article.objects.filter(q).all()  
    print([a.title for a in articles])  
    # ['鳥になりたい', '猫の額ほど狭い']  

↑の前者のOR検索では「Q(title__icontains='鳥') | Q(title__icontains='猫')」という条件を指定しています。
これは「titleに鳥、または猫が含まれる」という条件指定になります。
この条件だとArticletitleに鳥、または猫が含まれるレコードがヒットします。

またQオブジェクトをインスタンス化してqにして、このqのメソッドadd()を呼び出すことでも条件を追加できます(↑の後者のAND検索)。
add()の第1引数にはQオブジェクトで条件を指定します。
そして第2引数には演算子を指定します。
↑の場合だとQ.ORを指定しているので条件はOR検索用になります。

AND検索

QオブジェクトでAND検索する方法です
Qオブジェクトを「&」で繋げるとAND検索になります。

    # AND検索  
    articles = Article.objects.filter(  
        Q(title__icontains='犬') & Q(title__icontains='棒')  
    ).all()  
    print([a.title for a in articles])  
    # ['犬も歩けば棒に当たる']  

    # AND検索 その2  
    q = Q()  
    q.add(Q(title__icontains='犬'), Q.AND)  
    q.add(Q(title__icontains='棒'), Q.AND)  

    articles = Article.objects.filter(q).all()  
    print([a.title for a in articles])  
    # ['犬も歩けば棒に当たる']  

↑の前者のAND検索では「犬」と「棒」でAND検索しています。
この条件だとArticletitleに犬と棒が含まれるレコードがヒットします。

またAND検索もQオブジェクトのadd()で指定することができます
↑の後者のAND検索ではQオブジェクトをインスタンス化して、add()メソッドを呼び出しています。
add()の第1引数にはQオブジェクトで条件を指定し、第2引数にはQ.ANDを指定します。
こうすることでadd()で追加していく条件がANDで結合されます。

否定

Qオブジェクトを使うと否定条件も書くことが出来ます
否定にはQオブジェクトに「~」を指定します。

    # 否定  
    articles = Article.objects.filter(~Q(title__icontains='犬')).all()  
    print([a.title for a in articles])  
    # ['鳥になりたい', '猫の額ほど狭い']  

↑の場合だと「~Q(title__icontains='犬')」という条件を指定しています。
この条件だと「titleに犬を含まない記事」にレコードがヒットします。
また、この否定演算子はORやANDとも合わせて使うことが可能です。

おわりに

今回はDjangoのQオブジェクトについて解説しました。
Qオブジェクトは複雑な条件を指定して検索したい時に役立つオブジェクトです。
Djangoではわりと頻繁に使われます。
Qオブジェクトの使い方をマスターしておけばきっと役に立つでしょう。

🦝 < QあんどD

🐭 < QあんどDjangoね