ORM

Django ORMの全件取得入門|all・values・order_by

Django ORM 全件取得

Django ORMの全件取得入門
all・values・order_by

Django ORMでモデルの全データを取得する方法と、テンプレートでの表示方法を解説します。

こんな人向けの記事です

  • Django ORMで全データを取得したい人
  • QuerySetの基本的な使い方を知りたい人
  • テンプレートでデータを一覧表示したい人

Step 1allメソッドで全件取得

モデルの全データを取得するには、objects.all()メソッドを使用します。

Python
from myapp.models import Company

# 全件取得
companies = Company.objects.all()

# QuerySetが返される
print(type(companies))  # <class 'django.db.models.query.QuerySet'>
print(companies.count())  # データ件数

all()の戻り値はQuerySetというリストのようなオブジェクトです。QuerySetは遅延評価されるため、実際にデータにアクセスするまでSQLは実行されません。

ポイント: Company.objects.all()は全レコードを返すQuerySetを生成しますが、実際のSQLクエリはデータを使用する時点(forループ、スライス、評価時)で初めて実行されます。これを「遅延評価」と呼びます。

Step 2ビューでの使い方

ビューで全データを取得してテンプレートに渡す基本的なパターンです。

views.py
from django.views import View
from django.shortcuts import render
from .models import Company

class CompanyListView(View):
    def get(self, request):
        companies = Company.objects.all()
        context = {"companies": companies}
        return render(request, "myapp/company_list.html", context)

context辞書にQuerySetを入れてrenderに渡すことで、テンプレート内でcompaniesという変数名でデータにアクセスできます。

Step 3テンプレートでの表示

テンプレートではforタグを使ってデータを繰り返し表示します。

templates/myapp/company_list.html
<h1>会社一覧</h1>

<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>会社名</th>
      <th>設立日</th>
    </tr>
  </thead>
  <tbody>
    {% for company in companies %}
    <tr>
      <td>{{ company.id }}</td>
      <td>{{ company.name }}</td>
      <td>{{ company.founding_date }}</td>
    </tr>
    {% endfor %}
  </tbody>
</table>

Djangoテンプレートでは{{ 変数名.フィールド名 }}の形式でフィールドの値にアクセスします。ドット表記でオブジェクトの属性に直接アクセスできます。

Step 4並び替え(order_by)

取得するデータの並び順を指定するにはorder_by()を使います。

Python
# 名前の昇順
companies = Company.objects.all().order_by("name")

# 設立日の降順(-を付ける)
companies = Company.objects.all().order_by("-founding_date")

# 複数条件での並び替え
companies = Company.objects.all().order_by("name", "-founding_date")

ポイント: フィールド名の前に-(マイナス)を付けると降順になります。モデルのMetaクラスでorderingを設定しておくと、デフォルトの並び順を指定できます。

Step 5取得するフィールドの指定

全フィールドではなく、特定のフィールドのみ取得したい場合はvalues()values_list()を使います。

Python
# 辞書のリストとして取得
companies = Company.objects.all().values("name", "founding_date")
# [{"name": "会社A", "founding_date": ...}, ...]

# タプルのリストとして取得
companies = Company.objects.all().values_list("name", "founding_date")
# [("会社A", datetime.date(...)), ...]

# 1フィールドをフラットなリストで取得
names = Company.objects.all().values_list("name", flat=True)
# ["会社A", "会社B", "会社C"]

Step 6データが0件の場合の処理

データが存在しない場合のハンドリングも重要です。

Python
companies = Company.objects.all()

# 件数チェック
if companies.exists():
    print(f"{companies.count()}件のデータがあります")
else:
    print("データがありません")

テンプレートではemptyタグを使って0件の場合の表示を切り替えられます。

templates/myapp/company_list.html
{% for company in companies %}
  <div>{{ company.name }}</div>
{% empty %}
  <p>会社データがありません。</p>
{% endfor %}

ポイント: データの存在チェックにはexists()を使うのが最も効率的です。count()は件数をカウントするSQLを発行しますが、exists()は1件でも見つかった時点で処理を終了するため高速です。

まとめ

  • objects.all()で全データをQuerySetとして取得できる
  • QuerySetは遅延評価されるため、実際の使用時にSQLが実行される
  • テンプレートでは{% for %}タグで繰り返し表示する
  • order_by()で並び替え、-で降順を指定する
  • values()/values_list()で取得するフィールドを絞れる
  • {% empty %}タグで0件時の表示を制御する