필터링 (Filtering)과 정렬 (Ordering)

guava·2022년 1월 15일
0
post-custom-banner

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.

API에서 응답 데이터를 제공할 때 필터링 및 정렬이 필요할 수 있다.

rest_framework.filters에서 제공하는 필터 클래스를 APIView에 지정해서 원하는 조건에 맞게 필터링 및 정렬이 가능하다.
이를 통해 검색 기능도 간단하게 구현할 수 있다.

이번 포스팅에서는 DRF에서 활용하는 필터들의 사용법을 알아본다.

1. Filtering


  • 목록조회 APIView에서는 조건에 따라 필터링이 필요하다. (ex. QuerySet의 filter/exclude 등)
  • APIView 역시 Class Based View이다.

필터링에 필요한 인자 참조

APIView@api_view
self.request.userrequest.user
self.request.GETrequest.GET
self.request.query_params(GET과 동일)request.query_params (GET과 동일)
self.kwargs함수의 키워드 인자

1.1. 직접 Filtering의 예 → ListAPIView에서는 get_queryset 재정의


from rest_framework import generics

class PostListAPIView(generics.ListAPIView):
    queryset = Post.objects.all()

    def get_queryset(self):
        q = self.request.query_params.get('q', '')
        qs = super().get_queryset()
        if q:
            qs = qs.filter(title__icontains=q) # 적절히 필터링
        return qs

1.2. Generic Filtering / Ordering


Django Admin의 search 기능과 유사한 제공 → 별도의 검색엔진을 사용하는 것이 아니라, DBMS의 조건절 활용

from rest_framework.filters import SearchFilter, OrderingFilter

class PostModelViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['message'] # ?search= -> QuerySet 조건 절에 추가할 필드 지정. 모델 필드 중에 문자열 필드만을 지정.
    ordering_fields = ['id'] # ?ordering= -> 정렬을 허용할 필드의 화이트 리스트. 미지정 시에 serializer_class에 지정된 필드들.
    ordering = ['id'] # 디폴트 정렬을 지정
  • SearchFilter : search_fields를 기반으로 where조건절을 수행해준다.
  • OrderingFilter : ordering_fields, ordering을 참고
    • ordering_fields를 지정하지 않으면 모든 필드로 정렬이 가능하다.
  • [http://locahost:8000/post/search=수정&ordering=-id](http://locahost:8000/post/search=수정&ordering=-id) : "수정"이 포함된 포스트를 id 내림차순으로 정렬해서 보여준다.

search_fields

search_fields = ['=username', '=email']

  • 문자열 패턴 지정
    • "^" : Starts-with search
    • "=" : Exact matches
    • "@" : Full-text search. (단어/구문에 대한 검색, 장고의 MySQL 백엔드에서만 지원 - 2020년 2월 기준)
    • "$" : Regex search

→ get_search_fields 함수로도 구현 가능

post-custom-banner

0개의 댓글