ORM

Django ORMでOR条件を指定する|Qオブジェクトの使い方

DjangoのORMでfilter()に複数の条件を指定するとAND条件になりますが、OR条件で検索したい場合はQオブジェクトを使用します。複雑な条件式の組み立て方を解説します。

基本的な使い方

views.py
from django.db.models import Q

model = Company.objects.filter(Q(name='test') | Q(name='test2'))

説明

Step 1Qオブジェクトの基本

Djangoでは、Qオブジェクトを使用して複雑な条件式を作成することができます。OR条件を実現するには、以下の形式を使用します:

from django.db.models import Q

モデル.objects.filter(Q(条件) | Q(条件))

「|」演算子がOR条件を表します。

Step 2基本的な使用例

例えば、Companyモデルのnameフィールドが「test」または「test2」のデータを取得する場合:

from django.db.models import Q

companies = Company.objects.filter(Q(name='test') | Q(name='test2'))

上の例では、Companyモデルのnameフィールドがtestもしくはtest2のデータを取得しています。

Step 3複数条件の組み合わせ

Qオブジェクトでは、複数の条件を組み合わせることができます:

# OR条件の組み合わせ(3つ以上の条件)
companies = Company.objects.filter(
    Q(name='test') | Q(name='test2') | Q(name='test3')
)

# AND条件とOR条件の組み合わせ
companies = Company.objects.filter(
    Q(is_active=True) & (Q(name='test') | Q(name='test2'))
)

# OR条件とAND条件の組み合わせ
companies = Company.objects.filter(
    (Q(name='test') & Q(location='東京')) | (Q(name='test2') & Q(location='大阪'))
)

「&」演算子がAND条件を表し、括弧を使って条件の優先順位を指定できます。

Step 4複雑なフィルタリング

Qオブジェクトを使うと、より柔軟なフィルタリングが可能になります:

# 名前に「株式会社」を含むか、または従業員数が100以上の会社
companies = Company.objects.filter(
    Q(name__contains='株式会社') | Q(employee_count__gte=100)
)

# IDが特定のリストに含まれる、または特定の条件に一致する会社
target_ids = [1, 3, 5]
companies = Company.objects.filter(
    Q(id__in=target_ids) | Q(name__startswith='テスト')
)

Step 5NOT条件の使用

Qオブジェクトは「~」(チルダ)を使用して条件を否定することもできます:

# nameが「test」でない会社
companies = Company.objects.filter(~Q(name='test'))

# nameが「test」でなく、かつlocationが「東京」の会社
companies = Company.objects.filter(~Q(name='test') & Q(location='東京'))

# nameが「test」でなく、またはlocationが「東京」でない会社
companies = Company.objects.filter(~Q(name='test') | ~Q(location='東京'))

Step 6実践的な使用例

views.pyでのQオブジェクトの使用例:

from django.shortcuts import render
from django.db.models import Q
from .models import Company

def company_search(request):
    query = request.GET.get('q', '')
    location = request.GET.get('location', '')
    is_active = request.GET.get('active', None)
    
    # 基本クエリを作成
    companies = Company.objects.all()
    
    # 検索条件を追加
    if query:
        # 名前または説明に検索クエリが含まれる場合
        companies = companies.filter(
            Q(name__icontains=query) | Q(description__icontains=query)
        )
    
    # 場所のフィルター
    if location:
        companies = companies.filter(location=location)
    
    # アクティブステータスのフィルター
    if is_active is not None:
        is_active_bool = is_active == '1'
        companies = companies.filter(is_active=is_active_bool)
    
    return render(request, 'companies/search.html', {
        'companies': companies,
        'query': query,
        'location': location,
        'is_active': is_active
    })

検索フォームの例(search.html):

<form method="get">
    <div class="search-field">
        <label for="q">キーワード検索:</label>
        <input type="text" id="q" name="q" value="{{ query }}">
    </div>
    
    <div class="search-field">
        <label for="location">場所:</label>
        <select id="location" name="location">
            <option value="" {% if not location %}selected{% endif %}>すべて</option>
            <option value="東京" {% if location == '東京' %}selected{% endif %}>東京</option>
            <option value="大阪" {% if location == '大阪' %}selected{% endif %}>大阪</option>
            <option value="名古屋" {% if location == '名古屋' %}selected{% endif %}>名古屋</option>
        </select>
    </div>
    
    <div class="search-field">
        <label for="active">ステータス:</label>
        <select id="active" name="active">
            <option value="" {% if not is_active %}selected{% endif %}>すべて</option>
            <option value="1" {% if is_active == '1' %}selected{% endif %}>アクティブ</option>
            <option value="0" {% if is_active == '0' %}selected{% endif %}>非アクティブ</option>
        </select>
    </div>
    
    <button type="submit">検索</button>
</form>
注意点:
  • Qオブジェクトを使用するには、from django.db.models import Qのインポートが必要です。
  • 複雑な条件を使用する場合は、括弧を使って条件の優先順位を明確にすることをお勧めします。
  • Qオブジェクトは通常のfilterの条件と組み合わせることもできます。その場合、通常の条件はAND条件として扱われます。

まとめ

  • Qオブジェクトを|(パイプ)で繋ぐとOR条件になる
  • &でAND条件、~でNOT条件を表現できる
  • Qオブジェクトを使うとfilter()だけでは表現できない複雑な条件が書ける
  • 括弧を使って条件の優先順位を明示的に指定できる
  • from django.db.models import Qでインポートして使用する
  • 動的に条件を組み立てる場合にもQオブジェクトは便利