導入
「1000円以上の商品」「新しい順」。一覧ページは、条件で絞り、順番を整えて表示します。ORM の filter と order_by がその主役です。
説明
条件は フィールド名__演算子=値 という形(フィールドルックアップ)で書きます。
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
class Product(models.Model):
name = 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(Product)
data = [("りんご", 150, "果物"), ("みかん", 100, "果物"),
("牛乳", 200, "飲料"), ("お茶", 130, "飲料"), ("バナナ", 250, "果物")]
for name, price, cat in data:
Product.objects.create(name=name, price=price, category=cat)
# 絞り込み:果物だけ
fruits = Product.objects.filter(category="果物")
print("果物:", [p.name for p in fruits])
# 比較:150円以上(__gte = greater than or equal)
expensive = Product.objects.filter(price__gte=150)
print("150円以上:", [(p.name, p.price) for p in expensive])
# 部分一致:名前に「ん」を含む(__contains)
print("「ん」を含む:", [p.name for p in Product.objects.filter(name__contains="ん")])
# 除外:飲料以外(exclude)
print("飲料以外:", [p.name for p in Product.objects.exclude(category="飲料")])
# 並び替え:価格の高い順(- で降順)
for p in Product.objects.order_by("-price"):
print(p.price, p.name)
よく使うルックアップ:
price__gte/price__lte… 以上 / 以下(gt/ltは「より大きい/小さい」)。name__contains/name__startswith… 部分一致 / 前方一致。category__in=["果物", "飲料"]… いずれかに一致。filter(...).filter(...)のように、つなげて絞り込みを重ねられます(AND 条件)。order_by("price")は昇順、order_by("-price")は降順。
QuerySet は「遅延評価」で、実際に for で回したりリスト化したりするまでデータベースに問い合わせません。
やってみよう
filter(price__gte=150) の 150 を変える、order_by("-price") を order_by("name") にするなど、条件と並び順を変えて結果の変化を見てみましょう。
演習
price__lt=150(150円未満)で絞り込み、order_by("price")(安い順)で並べて、名前のリストを表示してください。出力に みかん が含まれれば成功です。
ヒント1を見る
cheap = Product.objects.filter(price__lt=150).order_by("price")。
ヒント2を見る
print([p.name for p in cheap])。