| この記事の要点 |
|
基本
Article.objects.order_by("created_at") # 昇順(古い順)
Article.objects.order_by("-created_at") # 降順(新しい順)
# 複数キー: 点数の高い順、同点なら名前の五十音順
Article.objects.order_by("-score", "title")
# 発行される SQL
print(Article.objects.order_by("-created_at").query)
# SELECT ... FROM "blog_article" ORDER BY "blog_article"."created_at" DESC
マイナスはフィールド名の直前に付けます。order_by("created_at DESC") のように SQL のキーワードを書くと FieldError になります。
並び順を後から変える・消す
qs = Article.objects.filter(published=True)
qs = qs.order_by("-created_at") # 追加ではなく「置き換え」
qs = qs.order_by("title") # 前の指定は消え、title 順になる
qs.reverse() # 指定済みの並びを逆にする
qs.order_by() # 並び順をすべて解除する
order_by() は累積しません。2 回呼んだら後の指定だけが残ります。段階的に組み立てたい場合はリストにためて最後に一度だけ渡します。
order = []
if sort_by_score:
order.append("-score")
order.append("-created_at")
qs = Article.objects.order_by(*order)
モデルの既定の並び順
class Article(models.Model):
title = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-created_at"] # 何も指定しなければこの順
Meta.ordering を付けると、すべてのクエリに ORDER BY が付きます。件数が多いテーブルでは、意図しないソートが性能に効いてくることがあります。
集計と組み合わせるときは特に注意が必要です。
from django.db.models import Count
# Meta.ordering のフィールドが GROUP BY に混ざり、結果が分かれてしまう
Article.objects.values("author").annotate(n=Count("id"))
# 集計の前に並び順を解除する
Article.objects.order_by().values("author").annotate(n=Count("id"))
リレーション先で並べる
Article.objects.order_by("-author__age") # 著者の年齢の降順
Article.objects.order_by("author__name", "-score") # 著者名順、同著者内は点数降順
# JOIN が増えるので select_related と併用する
Article.objects.select_related("author").order_by("-author__age")
アンダースコア 2 個でリレーションをたどります。1 個だとフィールド名として解釈され FieldError: Cannot resolve keyword になります。
集計値・計算値で並べる
from django.db.models import Count, F, Value
from django.db.models.functions import Coalesce, Lower
# コメント数の多い順
Article.objects.annotate(n=Count("comments")).order_by("-n")
# 計算した値で並べる
Article.objects.annotate(rate=F("likes") * 100 / F("views")).order_by("-rate")
# 大文字小文字を無視して並べる
Article.objects.order_by(Lower("title"))
# NULL を 0 として扱う
Article.objects.order_by(Coalesce("score", Value(0)).desc())
NULL の位置を制御する
from django.db.models import F
Article.objects.order_by(F("published_at").desc(nulls_last=True))
Article.objects.order_by(F("published_at").asc(nulls_first=True))
| DB | 既定の NULL の位置(昇順) |
|---|---|
| PostgreSQL | 最後 |
| MySQL / MariaDB | 最初 |
| SQLite | 最初 |
開発が SQLite で本番が MySQL といった構成では、同じコードでも並びが変わります。nulls_last を明示すれば揃います。
ランダム・件数制限との組み合わせ
Article.objects.order_by("?")[:5] # ランダム 5 件(大量データでは重い)
Article.objects.order_by("-created_at")[:10] # 新着 10 件
Article.objects.order_by("-created_at")[10:20] # 11〜20 件目
Article.objects.latest("created_at") # 最も新しい 1 件
Article.objects.earliest("created_at") # 最も古い 1 件
スライスした後は order_by() や filter() を呼べません(Cannot filter a query once a slice has been taken.)。絞り込みと並べ替えを済ませてから最後にスライスします。件数制限の詳細は limit, offsetの指定方法 を参照してください。
大量データで遅いとき
class Article(models.Model):
created_at = models.DateTimeField(db_index=True) # 単一キー
class Meta:
indexes = [
models.Index(fields=["-created_at", "id"]), # 複合+降順
]
ORDER BY に使う列にインデックスが無いと、DB は毎回すべての行を並べ替えます。並び順とインデックスの順序を一致させるのが基本です。実際に効いているかは qs.explain() で確認できます(SQLのログ出力方法)。
関連
- データベースへの接続と操作 — 親カテゴリ
- filterの検索オプション
- limit, offsetの指定方法
- SELECT, INSERT, UPDATE, DELETE
- SQLのログ出力方法
- 素のSQLを直接実行する方法
子ページ
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38