ORM

Django ORMのget入門|フィールド値で1件取得する方法

Django ORM

Django ORMのget入門
フィールド値で1件取得する方法

Django ORMのget()メソッドを使って、特定のフィールド値に一致するデータを1件だけ取得する方法を解説します。

こんな人向けの記事です

  • Django ORMの基本的なデータ取得方法を学びたい人
  • get()とfilter()の違いを理解したい人
  • get()使用時の例外処理を知りたい人

Step 1get()メソッドの基本

Django ORMで特定のフィールドの値に一致するデータを1件だけ取得するには、get()メソッドを使用します。

Python
# models.py
from django.db import models

class Company(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField(unique=True)
    founded_date = models.DateField(null=True)

    def __str__(self):
        return self.name
Python
# views.py
from .models import Company

def company_detail(request):
    # nameフィールドが"テスト株式会社"のデータを1件取得
    company = Company.objects.get(name="テスト株式会社")
    print(company.name)   # テスト株式会社
    print(company.email)  # test@example.com
実行結果
テスト株式会社
test@example.com

get()は条件に一致するレコードがちょうど1件のときだけ正常に動作します。0件または2件以上の場合は例外が発生します。

Step 2get()の例外処理

get()メソッドは2種類の例外を発生させる可能性があります。実務では必ず例外処理を行いましょう。

Python
from django.http import Http404

def company_detail(request, company_name):
    try:
        company = Company.objects.get(name=company_name)
    except Company.DoesNotExist:
        # 一致するデータが0件の場合
        raise Http404("該当する会社が見つかりません")
    except Company.MultipleObjectsReturned:
        # 一致するデータが2件以上の場合
        company = Company.objects.filter(name=company_name).first()

    return render(request, "company/detail.html", {"company": company})
get_object_or_404を使う方法
Djangoにはget_object_or_404()というショートカットがあり、DoesNotExist例外を自動的にHttp404に変換してくれます。
from django.shortcuts import get_object_or_404
company = get_object_or_404(Company, name="テスト株式会社")

Step 3複数条件での取得

get()メソッドでは、複数の条件をキーワード引数で指定できます。すべての条件がANDで結合されます。

Python
# 複数条件(AND)で1件取得
company = Company.objects.get(
    name="テスト株式会社",
    email="test@example.com"
)

# フィールドルックアップを使った条件指定
# nameが"テスト"で始まるデータを1件取得
company = Company.objects.get(name__startswith="テスト")

# idで取得(最もよく使うパターン)
company = Company.objects.get(id=1)
company = Company.objects.get(pk=1)  # pkはidのエイリアス
注意
get()にルックアップを使うと、一致するデータが2件以上存在する可能性が高くなります。name__startswithなどを使う場合はfilter().first()のほうが安全です。

Step 4get()とfilter()の使い分け

get()filter()は似ていますが、戻り値と動作が異なります。

Python
# get(): モデルインスタンスを1つ返す
company = Company.objects.get(id=1)
print(type(company))  # <class 'app.models.Company'>
print(company.name)   # 直接フィールドにアクセス可能

# filter(): QuerySetを返す(0件以上)
companies = Company.objects.filter(name="テスト株式会社")
print(type(companies))  # <class 'django.db.models.query.QuerySet'>
for company in companies:
    print(company.name)  # ループで処理

# filter().first(): 最初の1件またはNoneを返す
company = Company.objects.filter(name="テスト株式会社").first()
if company:
    print(company.name)
else:
    print("見つかりませんでした")
実行結果
<class 'app.models.Company'>
テスト株式会社
<class 'django.db.models.query.QuerySet'>
テスト株式会社
使い分けの指針
get()を使う場面: id、メールアドレスなどユニークなフィールドで検索するとき
filter().first()を使う場面: 該当データが存在しない可能性がある場合や、ユニーク制約のないフィールドで検索するとき

Step 5実践的な使用例

実際のDjangoビューでのget()の使い方を紹介します。

Python
# views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from .models import Company

# パターン1: get_object_or_404を使う(推奨)
def company_detail(request, pk):
    company = get_object_or_404(Company, pk=pk)
    return render(request, "company/detail.html", {"company": company})

# パターン2: try-exceptで細かく制御
def company_search(request):
    name = request.GET.get("name", "")
    if not name:
        messages.warning(request, "会社名を入力してください")
        return redirect("company_list")

    try:
        company = Company.objects.get(name=name)
        return redirect("company_detail", pk=company.pk)
    except Company.DoesNotExist:
        # 完全一致で見つからない場合、部分一致で検索
        companies = Company.objects.filter(name__icontains=name)
        if companies.exists():
            messages.info(request, "完全一致はありませんが、類似の会社が見つかりました")
            return render(request, "company/list.html", {"companies": companies})
        else:
            messages.error(request, "該当する会社が見つかりません")
            return redirect("company_list")

まとめ

  • get()はフィールドの値が一致するデータを1件だけ取得する
  • 0件の場合はDoesNotExist、2件以上の場合はMultipleObjectsReturned例外が発生する
  • 実務ではget_object_or_404()を使うのが便利で安全
  • ユニーク制約のないフィールドにはfilter().first()がおすすめ
  • 複数条件はキーワード引数で指定し、AND条件として結合される