DRF의 목록 API는 쿼리 파라미터로 결과를 좁히는 세 가지 장치를 붙일 수 있다. 값이 정확히 맞는 것만 고르는 필터, 일부 문자열로 찾는 검색, 순서를 바꾸는 정렬이다. 모두 제네릭 뷰(GenericAPIView 계열)의 filter_backends로 적용된다.
가장 단순한 방법
class ReviewList(generics.ListAPIView):
serializer_class = ReviewSerializer
def get_queryset(self):
qs = Review.objects.all()
if user := self.request.query_params.get("user"):
qs = qs.filter(author__username=user)
return qs규칙이 한두 개면 이걸로 충분하다.
백엔드 붙이기
from django_filters.rest_framework import DjangoFilterBackend
class WatchListView(generics.ListAPIView):
queryset = WatchList.objects.all()
serializer_class = WatchListSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ["platform__name", "active"] # ?platform__name=Netflix&active=true
search_fields = ["title", "=platform__name"] # ?search=dune (=는 정확히 일치)
ordering_fields = ["avg_rating", "created"] # ?ordering=-avg_rating- DjangoFilterBackend(django-filter 패키지): 기본은 정확히 일치. 연관 모델 필드는
__로 따라간다. 범위·부분 일치가 필요하면FilterSet클래스를 정의한다. 예전 이름filter_fields는filterset_fields로 바뀌었다 - SearchFilter:
search_fields의 필드들에서 대소문자 무시(case-insensitive) 부분 일치(icontains)로 찾는다. 접두사^는 시작 일치,=는 정확히 일치 - OrderingFilter:
?ordering=필드, 앞에-면 내림차순. 허용할 필드는ordering_fields로 정한다. 지정하지 않으면 시리얼라이저의 읽기 필드만 허용되고,"__all__"로 모든 모델 필드를 열면 응답에 없는 필드로 정렬해 그 값을 추측당할 수 있다
주의
SearchFilter의 부분 일치는 앞 와일드카드LIKE라 데이터가 많으면 느리다. 본격적인 검색은 PostgreSQL 전문 검색(full-text search)이나 검색 엔진으로 옮긴다- 필터링 대상 컬럼에는 인덱스를 건다
- 필터·정렬은 페이지네이션 (offset·cursor)과 함께 쓰이고, 커서 페이지네이션과 정렬을 같이 쓸 때는 정렬 필드를 제한한다
뷰 구조는 DRF 뷰 계층를 본다.
출처: DRF Filtering: Filtering against query parameters · DjangoFilterBackend · SearchFilter · OrderingFilter