Django ORMの全件取得入門
all・values・order_by
Django ORMでモデルの全データを取得する方法と、テンプレートでの表示方法を解説します。
こんな人向けの記事です
- Django ORMで全データを取得したい人
- QuerySetの基本的な使い方を知りたい人
- テンプレートでデータを一覧表示したい人
Step 1allメソッドで全件取得
モデルの全データを取得するには、objects.all()メソッドを使用します。
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ビューでの使い方
ビューで全データを取得してテンプレートに渡す基本的なパターンです。
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タグを使ってデータを繰り返し表示します。
<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()を使います。
# 名前の昇順
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()を使います。
# 辞書のリストとして取得
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件の場合の処理
データが存在しない場合のハンドリングも重要です。
companies = Company.objects.all()
# 件数チェック
if companies.exists():
print(f"{companies.count()}件のデータがあります")
else:
print("データがありません")
テンプレートではemptyタグを使って0件の場合の表示を切り替えられます。
{% 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件時の表示を制御する