ORM

Django ORMのfirst・last入門|最初・最後のデータを取得する方法

Django ORM

Django ORMのfirst・last入門
最初・最後のデータを取得する方法

Django ORMのfirst()とlast()メソッドを使って、QuerySetの最初または最後のデータを安全に取得する方法を解説します。

こんな人向けの記事です

  • Django ORMで先頭や末尾のデータを取得したい人
  • first()とget()の違いを理解したい人
  • latest()やearliest()の使い方を知りたい人

Step 1first()の基本

first()はQuerySetの最初の1件を返します。データが存在しない場合は例外ではなくNoneを返すため、安全に使えます。

Python
# models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    view_count = models.IntegerField(default=0)
    is_published = models.BooleanField(default=False)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.title
Python
# 最初の1件を取得
article = Article.objects.first()
if article:
    print(f"最初の記事: {article.title}")
else:
    print("記事がありません")

# order_by()と組み合わせる
oldest = Article.objects.order_by("created_at").first()
print(f"最も古い記事: {oldest.title}")

most_viewed = Article.objects.order_by("-view_count").first()
print(f"最も閲覧された記事: {most_viewed.title}")

# filter()と組み合わせる
latest_published = Article.objects.filter(
    is_published=True
).order_by("-created_at").first()
if latest_published:
    print(f"最新の公開記事: {latest_published.title}")
実行結果
最初の記事: Django ORM活用術
最も古い記事: はじめてのPython
最も閲覧された記事: Django入門ガイド
最新の公開記事: Django ORM活用術

Step 2last()の基本

last()はQuerySetの最後の1件を返します。first()と同様に、データがない場合はNoneを返します。

Python
# 最後の1件を取得
article = Article.objects.last()
if article:
    print(f"最後の記事: {article.title}")

# order_by()と組み合わせ
# created_at昇順の最後 = 最新の記事
newest = Article.objects.order_by("created_at").last()
print(f"最新の記事: {newest.title}")

# 最も閲覧が少ない記事
least_viewed = Article.objects.order_by("-view_count").last()
print(f"最も閲覧が少ない: {least_viewed.title}")
実行結果
最後の記事: はじめてのPython
最新の記事: Django ORM活用術
最も閲覧が少ない: テスト記事
orderingの影響に注意
Metaクラスでorderingが設定されている場合、first()last()はその並び順に従います。ordering = ["-created_at"]の場合、first()は最新の記事を返します。明示的にorder_by()を指定すると上書きされます。

Step 3latest()とearliest()

latest()earliest()は日時フィールドを基準に最新・最古のデータを取得する専用メソッドです。

Python
# latest(): 指定フィールドの値が最大(最新)のレコード
latest_article = Article.objects.latest("created_at")
print(f"最新: {latest_article.title} ({latest_article.created_at})")

# earliest(): 指定フィールドの値が最小(最古)のレコード
earliest_article = Article.objects.earliest("created_at")
print(f"最古: {earliest_article.title} ({earliest_article.created_at})")

# filter()と組み合わせ
latest_published = Article.objects.filter(
    is_published=True
).latest("created_at")
print(f"最新の公開記事: {latest_published.title}")

# Metaクラスでget_latest_byを設定すると引数を省略できる
class Article(models.Model):
    title = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        get_latest_by = "created_at"

# 引数なしで呼べる
latest = Article.objects.latest()  # created_atが最新のもの
実行結果
最新: Django ORM活用術 (2025-01-15 10:30:00)
最古: はじめてのPython (2024-03-01 09:00:00)
最新の公開記事: Django ORM活用術
latest()とearliest()の例外
latest()earliest()は該当データがない場合、DoesNotExist例外を発生させます。first()のようにNoneを返しません。データがない可能性がある場合はtry-exceptで囲むか、first()を使ってください。

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

Python
# get(): 1件だけ取得(0件や2件以上で例外)
try:
    article = Article.objects.get(title="Django入門")
except Article.DoesNotExist:
    print("見つかりません")
except Article.MultipleObjectsReturned:
    print("2件以上見つかりました")

# first(): 最初の1件またはNone(例外なし)
article = Article.objects.filter(title="Django入門").first()
if article:
    print(article.title)

# 比較表
# | メソッド    | 0件時        | 1件時            | 2件以上時            |
# |-------------|--------------|------------------|----------------------|
# | get()       | DoesNotExist | インスタンス     | MultipleObjects      |
# | first()     | None         | インスタンス     | 最初の1件            |
# | last()      | None         | インスタンス     | 最後の1件            |
# | latest()    | DoesNotExist | インスタンス     | 最新の1件            |
# | earliest()  | DoesNotExist | インスタンス     | 最古の1件            |
# | [0]         | IndexError   | インスタンス     | 最初の1件            |

Step 5実践的な使用例

Python
# views.py
from django.shortcuts import render
from .models import Article

def home(request):
    # 最新の公開記事5件
    latest_articles = Article.objects.filter(
        is_published=True
    ).order_by("-created_at")[:5]

    # 最も人気の記事
    most_popular = Article.objects.filter(
        is_published=True
    ).order_by("-view_count").first()

    # 最新の記事(latest()を使用)
    try:
        newest = Article.objects.filter(
            is_published=True
        ).latest("created_at")
    except Article.DoesNotExist:
        newest = None

    context = {
        "latest_articles": latest_articles,
        "most_popular": most_popular,
        "newest": newest,
    }
    return render(request, "home.html", context)

# ユーザーの最終ログイン日を取得
def user_profile(request, user_id):
    from django.contrib.auth.models import User
    user = User.objects.get(id=user_id)
    print(f"最終ログイン: {user.last_login}")

    # ユーザーの最新の記事
    latest = Article.objects.filter(
        author=user
    ).order_by("-created_at").first()
    if latest:
        print(f"最新記事: {latest.title}")

まとめ

  • first()はQuerySetの最初の1件を返し、0件ならNoneを返す
  • last()はQuerySetの最後の1件を返し、0件ならNoneを返す
  • latest()earliest()は日時フィールド基準で取得(0件時は例外)
  • データの有無が不確実な場合はfirst()が最も安全
  • ユニークなフィールドでの検索にはget()、それ以外はfirst()を使い分ける