本文へスキップ
BecomeCoder

Djangoコース · 第5章 モデルとデータベース · レッスン24

集計と複雑な条件 ― count / aggregate / Q

ブラウザで完結

導入

「合計金額」「平均点」「A または B」。一覧を出すだけでなく、数字を集計したり、複雑な条件で絞ったりしたくなります。ORM はそれもこなします。

説明

import django
from django.conf import settings
if not settings.configured:
    settings.configure(DEBUG=True, SECRET_KEY="dev", INSTALLED_APPS=[],
        DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}})
    django.setup()

from django.db import models, connection
from django.db.models import Sum, Avg, Max, Min, Q

class Sale(models.Model):
    item = models.CharField(max_length=50)
    price = models.IntegerField()
    category = models.CharField(max_length=20)
    class Meta:
        app_label = "shop"

with connection.schema_editor() as schema:
    schema.create_model(Sale)

for item, price, cat in [("りんご", 150, "果物"), ("牛乳", 200, "飲料"),
                         ("みかん", 100, "果物"), ("お茶", 130, "飲料")]:
    Sale.objects.create(item=item, price=price, category=cat)

# 集計:合計・平均・最大(aggregate は辞書で返る)
print(Sale.objects.aggregate(Sum("price"), Avg("price"), Max("price")))

# 件数
print("果物の件数:", Sale.objects.filter(category="果物").count())

# OR 条件:category が果物 「または」 price が 180 以上
q = Sale.objects.filter(Q(category="果物") | Q(price__gte=180))
print("果物 or 180円以上:", [s.item for s in q])

# AND / NOT も Q で書ける: 飲料 かつ 150円未満ではない
q2 = Sale.objects.filter(Q(category="飲料") & ~Q(price__lt=150))
print("飲料 かつ 150円以上:", [s.item for s in q2])
  • aggregate(Sum("price")) … 合計。AvgMaxMinCount も同様。結果は {"price__sum": 580} のような辞書。
  • 通常の filter(a=1, b=2)AND(両方満たす)。
  • ORNOT を書きたいときは Q オブジェクトを使います。| が OR、& が AND、~ が NOT。

やってみよう

aggregateMin("price") を足す、Q(...) の条件を変えるなどして、集計結果と絞り込み結果の変化を確かめましょう。

演習

Q を使って「category が飲料 または item が りんご」のレコードを絞り込み、その item のリストを表示してください。出力に りんご牛乳 が含まれれば成功です。

ヒント1を見る

Sale.objects.filter(Q(category="飲料") | Q(item="りんご"))

ヒント2を見る

print([s.item for s in q])

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

Python — ライブラリ付きで実行(Pyodide)

numpy / pandas / matplotlib が使える本物のPython(Pyodide)を読み込みます。初回のみ読み込みに少し時間がかかります(以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。