ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
filter の基本
filter() はSQL WHERE 句を Python から組み立てるメソッドです。返り値は QuerySet(遅延評価)で、実行は list() / for / .exists() 等で行われます。
from myapp.models import User, Article
# 単一条件
users = User.objects.filter(name="太郎")
# SQL: SELECT * FROM users WHERE name = '太郎'
# 複数条件(AND)
users = User.objects.filter(name="太郎", age=30)
# チェーン(同じく AND)
users = User.objects.filter(active=True).filter(role="admin")
# 否定
inactive = User.objects.exclude(active=True)
# 件数
count = User.objects.filter(active=True).count()
# 存在確認(速い)
if User.objects.filter(email="x@example.com").exists():
pass
# 1件取得
u = User.objects.filter(id=1).first() # None になり得る
u = User.objects.get(id=1) # 0件 / 2件以上で例外
lookup 一覧
| lookup | 意味 | SQL 例 |
|---|---|---|
exact | 完全一致(デフォルト) | = 'a' |
iexact | 大小無視の完全一致 | LOWER(...) = 'a' |
contains | 部分一致 | LIKE '%a%' |
icontains | 大小無視の部分一致 | ILIKE '%a%' |
startswith / istartswith | 前方一致 | LIKE 'a%' |
endswith / iendswith | 後方一致 | LIKE '%a' |
gt / gte / lt / lte | 大小比較 | > / >= / < / <= |
in | リスト内 | IN (1, 2, 3) |
range | 範囲(両端含む) | BETWEEN a AND b |
isnull | NULL 判定 | IS NULL / IS NOT NULL |
regex / iregex | 正規表現 | REGEXP |
date / year / month / day | 日付の部分抽出 | YEAR(d) = 2026 |
hour / minute / week_day | 時刻・曜日 | 同上 |
lookup の使用例
# 大小無視で部分一致
Article.objects.filter(title__icontains="django")
# 18 歳以上
User.objects.filter(age__gte=18)
# 18-65 歳
User.objects.filter(age__range=(18, 65))
# 特定の ID 群
User.objects.filter(id__in=[1, 2, 3])
# email が NULL
User.objects.filter(email__isnull=True)
# email が NOT NULL
User.objects.filter(email__isnull=False)
# 2026 年の記事
Article.objects.filter(published_at__year=2026)
Article.objects.filter(published_at__year=2026, published_at__month=5)
# 日付範囲
from datetime import date
Article.objects.filter(published_at__date__range=(date(2026, 1, 1), date(2026, 5, 17)))
# 正規表現
User.objects.filter(email__regex=r"^[a-z]+@example\.com$")
# 外部キーを辿る(__ で何段でも)
Article.objects.filter(author__profile__country="JP")
Q オブジェクト: OR / NOT / 複雑条件
filter のキーワード引数はすべて AND。OR や複雑な括弧条件は Q を使います:
from django.db.models import Q
# OR
User.objects.filter(Q(name="太郎") | Q(name="花子"))
# AND(同じだが明示的に)
User.objects.filter(Q(active=True) & Q(role="admin"))
# NOT
User.objects.filter(~Q(role="guest"))
# 複雑な括弧
# (active=True AND role='admin') OR (vip=True)
User.objects.filter(
(Q(active=True) & Q(role="admin")) | Q(vip=True)
)
# キーワード引数と Q の混在も OK(Q は前、キーワードは後ろ)
User.objects.filter(Q(role="admin") | Q(role="manager"), active=True)
F 式: 別カラム同士の比較
「price が cost より高い商品」のように同じテーブルの別カラム同士を比較するときは F:
from django.db.models import F
# 別カラム比較
Product.objects.filter(price__gt=F("cost"))
# 演算
Product.objects.filter(price__gt=F("cost") * 1.2) # 価格が原価の 1.2 倍超
# 更新(読みと書きが 1 クエリで完結)
Product.objects.filter(stock__gt=0).update(stock=F("stock") - 1)
annotate + filter(集約後のフィルタ)
from django.db.models import Count, Avg, Sum
# 投稿数が 3 件以上のユーザ
User.objects.annotate(
post_count=Count("articles")
).filter(post_count__gte=3)
# カテゴリ別の平均価格 100 円以上
Product.objects.values("category").annotate(
avg_price=Avg("price")
).filter(avg_price__gte=100)
# annotate の前と後で filter は意味が違う
# 前: 集約対象を絞る 後: 集約結果を絞る
User.objects.filter(articles__published=True).annotate(c=Count("articles"))
# → 公開記事数
User.objects.annotate(c=Count("articles")).filter(c__gte=3)
# → 全記事数が 3 件以上のユーザ
django-filter(DRF と組合せ)
Django REST Framework でクエリパラメータからの絞り込みを簡単にするライブラリ:
# pip install django-filter
# filters.py
import django_filters
from .models import Article
class ArticleFilter(django_filters.FilterSet):
title = django_filters.CharFilter(lookup_expr="icontains")
min_views = django_filters.NumberFilter(field_name="views", lookup_expr="gte")
published_after = django_filters.DateFilter(field_name="published_at", lookup_expr="gte")
class Meta:
model = Article
fields = ["category", "author"]
# views.py (DRF)
from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend
class ArticleListView(generics.ListAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = ArticleFilter
# GET /articles/?title=django&min_views=100&published_after=2026-01-01
パフォーマンスの注意
icontainsはインデックスが効かない。大量データなら全文検索 (PostgreSQL trigram / Elasticsearch) を検討- 外部キーをまたぐ filter はJOIN が増える →
select_related/prefetch_related併用 .count()より.exists()が速い(存在チェック用途なら)filter(...).filter(...)は多対多経由だと意味が変わる(同じレコードか別レコードか)- SQL を確認:
print(queryset.query)またはdjango-debug-toolbar
FAQ
Q: filter と get の違い
A: filter は QuerySet(0 件でも OK)、get は単一オブジェクト(0 件 / 2 件以上で例外)。「無ければ None」なら .first()。
Q: NULL を含めて検索したい
A: filter(Q(email="") | Q(email__isnull=True)) のように Q で OR。
Q: 動的に lookup を組み立てたい
A: **{f"{field}__icontains": keyword} のように辞書アンパックで渡す。または Q を reduce(operator.or_, [Q(...), ...])。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Laravel キャッシュクリア完全ガイド(cache:clear / config:clear / 2026-05-18 07:42:07
- プロジェクトの作成と削除 2026-05-18 07:42:07
- インストール直後にNetbeansが反応しない 2026-05-18 07:42:07
- 動画やチャンネルの検索 2026-05-18 07:42:07
- APIキー取得方法 2026-05-18 07:42:07
- チャンネル情報の取得 2026-05-18 07:42:07
- API 入門 — Web API(REST / GraphQL / gRPC / 2026-05-18 07:42:07
- インストール(eclipseプラグイン) 2026-05-18 07:42:07
- Laravel「Dotenv values containing spaces must be surrounded 2026-05-18 07:42:07
- エラー一覧 2026-05-18 07:42:07
- curl: (51) SSL: certificate subject name '~' does not match 2026-05-18 07:42:07
- インストール方法(Windows版) 2026-05-18 07:42:07
- JSONから配列に変換 2026-05-18 07:42:07
- 処理を一定時間待つ 2026-05-18 07:42:07
- A non well formed numeric value encountered 2026-05-18 07:42:07
コメントを削除してもよろしいでしょうか?