ORM

Django ORMのexists入門|データの存在確認方法

Django ORMでデータベースにレコードが存在するかどうかを確認する方法を解説します。exists()メソッドを使うと、実際のデータを取得せずに存在チェックだけを効率的に行えます。

基本的な使い方

exists()メソッドは、クエリセットにレコードが1件以上あればTrue、なければFalseを返します。

views.py
from .models import Person

def index(request):
    # 20歳以上のPersonが存在するか確認
    has_adults = Person.objects.filter(age__gte=20).exists()
    print(has_adults)  # True or False
実行結果
True

filter()で条件を絞り込んだクエリセットに対して.exists()を呼ぶだけで、存在確認ができます。

条件なしの存在確認

テーブルにデータが1件でもあるかどうかを確認する場合は、条件なしで使います。

views.py
# テーブルにデータが存在するか
Person.objects.exists()

# 上記と同じ意味
Person.objects.all().exists()

特定の条件での存在確認

様々なフィルタ条件と組み合わせて、特定のレコードが存在するかを確認できます。

views.py
# IDが5のレコードが存在するか
Person.objects.filter(id=5).exists()

# nameが"山田太郎"のレコードが存在するか
Person.objects.filter(name="山田太郎").exists()

# emailで存在確認
Person.objects.filter(email="example@test.com").exists()

複数条件での存在確認

filter()に複数の条件を指定すると、AND条件での存在確認が行えます。

views.py
# 30歳以上の男性が存在するか
Person.objects.filter(age__gte=30, gender="男性").exists()

# 特定の部署の管理職が存在するか
Person.objects.filter(department="営業部", position="マネージャー").exists()

関連モデルを使った存在確認

ForeignKeyやManyToManyで紐づいた関連モデルのデータが存在するかも確認できます。

views.py
# ユーザーが投稿を持っているか確認
user = User.objects.get(id=1)
user.post_set.exists()

# 特定のカテゴリの記事が存在するか
category = Category.objects.get(name="Django")
category.article_set.exists()

# 条件付きで関連データの存在を確認
user.post_set.filter(is_published=True).exists()

実践的な使用例

ビューでのexists()の活用例を紹介します。

views.py
from django.shortcuts import redirect, render
from django.contrib import messages
from .models import User

def show_user(request, user_id):
    # ユーザーが存在しない場合はリダイレクト
    if not User.objects.filter(id=user_id).exists():
        messages.warning(request, "指定されたユーザーは存在しません")
        return redirect('user_list')

    user = User.objects.get(id=user_id)
    return render(request, 'users/show.html', {'user': user})

def admin_dashboard(request):
    # 管理者が存在しない場合は初期セットアップへ
    if not User.objects.filter(role="admin").exists():
        return redirect('setup_admin')
    # ダッシュボードの処理
    return render(request, 'admin/dashboard.html')
ポイント

exists()は内部的にSELECT 1 ... LIMIT 1というSQLを実行するため、count() > 0len(queryset) > 0よりも高速です。存在確認だけが目的の場合は、必ずexists()を使いましょう。

注意

exists()get()の使い分けに注意してください。exists()はデータの有無だけを確認し、get()は実際のオブジェクトを返します。データを使う必要がある場合はget()filter()を使用してください。

まとめ

  • exists()はクエリセットにデータがあればTrue、なければFalseを返す
  • filter()と組み合わせて条件付きの存在確認ができる
  • 関連モデルに対してもexists()で存在確認が可能
  • count() > 0よりもexists()の方がパフォーマンスが良い
  • ビューでの条件分岐やバリデーションに活用すると効果的