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オブジェクトは便利