# 3.4 フィルタリングと検索の実装パターン(Django REST Framework 編)
前回の記事ではエラーハンドリングについてまとめた。
今回は業務システムで必ず必要になる フィルタリングと検索 を取り上げる。
一覧 API に「検索条件をつけたい」「大量データをページングしたい」というニーズは多く、
Django REST Framework(DRF)ではそれをシンプルに実現できる。
1. django-filter を使った検索
まずは定番の django-filter を利用する方法。
セットアップ
pip install django-filter
設定に追加:
# settings.py
REST_FRAMEWORK = {
"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
}
フィルタクラスを定義
# filters.py
import django_filters
from .models import Order
class OrderFilter(django_filters.FilterSet):
date_from = django_filters.DateFilter(field_name="created_at", lookup_expr="gte")
date_to = django_filters.DateFilter(field_name="created_at", lookup_expr="lte")
class Meta:
model = Order
fields = ["customer_name", "date_from", "date_to"]
ViewSet に適用
# views.py
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from .models import Order
from .serializers import OrderSerializer
from .filters import OrderFilter
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = OrderFilter
実行例
GET /api/orders/?customer_name=株式会社テスト&date_from=2024-01-01&date_to=2024-01-31
2. キーワード検索(部分一致)
フィルタだけでなく「フリーワード検索」を加えると便利。
from rest_framework import filters
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_class = OrderFilter
search_fields = ["customer_name"]
実行例:
GET /api/orders/?search=テスト
部分一致でヒットする。
3. ソート(並び替え)
検索結果を並び替えたいときは OrderingFilter を使う。
from rest_framework import filters
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_class = OrderFilter
search_fields = ["customer_name"]
ordering_fields = ["created_at", "total_amount"]
ordering = ["-created_at"] # デフォルト
実行例:
GET /api/orders/?ordering=total_amount
GET /api/orders/?ordering=-created_at
4. ページネーション
大量データを扱う場合はページネーションが必須。
設定でグローバルに指定
# settings.py
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 50
}
レスポンス例
{
"count": 120,
"next": "http://example.com/api/orders/?page=2",
"previous": null,
"results": [
{ "id": 1, "customer_name": "株式会社テスト", "total_amount": 50000 },
{ "id": 2, "customer_name": "サンプル商事", "total_amount": 120000 }
]
}
他のページネーション方式
-
LimitOffsetPagination:
?limit=10&offset=20 - CursorPagination: 大量データでも安定、無限スクロール向け
5. 業務システムでの工夫
-
複数条件を組み合わせやすい設計
→django-filterでフィールドごとにフィルタ定義 -
検索条件の履歴保存
→ フロントと組み合わせて「前回の条件を再現」できるようにする -
一覧と集計の使い分け
→ 大量データを返すより「条件で絞って集計値だけ返す」API を分けた方が効率的
AI活用の進め方
フィルタリングや検索処理も、AI と相性が良い分野。
ただし、注意すべき点がいくつかある。
-
最初はおまかせで依頼する
たとえば「django-filter を使った検索を実装して」と伝えれば、基本的な雛形はすぐ生成される。 -
既存のフィルタクラスを例示する
プロジェクト固有のフィールド名や検索条件がある場合は、その一部を例示して「同じ形式で追加して」と指示すると精度が上がる。 -
複雑な検索条件は分割して依頼する
AND / OR 条件、外部キーをまたぐ検索、集計 API などは AI が苦手なケース。
この場合は「まず単純な検索を作る」「次に集計専用 API を作る」と段階的に依頼した方が確実。
AI は定番の検索やページネーション実装を素早く書くのに非常に有効だが、
「どこまで API で返すか」「どこからはフロント側で処理するか」 は設計判断が必要。
この線引きをエンジニアが明確にしないと、AI が出力したコードが使いづらくなる。
まとめ
DRF でフィルタリングと検索を実装する際のポイントは次の通り。
-
django-filterを使えば検索条件を簡単に定義できる -
SearchFilterやOrderingFilterでキーワード検索・並び替えが可能 - ページネーションを組み合わせて大量データに対応する
- 業務システムでは「検索条件の履歴」「集計 API」といった工夫も有効
- AI 活用では雛形生成に頼りつつ、複雑条件は設計を分けて指示するのが効率的
次回は パフォーマンス改善と N+1 対策 をテーマにまとめる予定。
Discussion