Mawa Town

Mawaという人が作る小さな町でMawaTownです。技術と音楽が好き。

DRF::ListViewで複数のクエリでフィルタリングする方法

Django

Django

SearchFilterだけだと足りないことが多々あり・・・

DRFで、SearchFilterという機能があり、次のようにすると、

api.views
#url article_list とします

class ArticleListAPIView(ListAPIView):
    permission_classes = [AllowAny]
    queryset = Article.objects.all()
    serializer_class = ArticleListSerializer
    filter_backends= [SearchFilter]
    search_fields = ['title',
                     'article_description',
                    ]

titleとarticle_descriptionに指定の文字列があるものだけ抽出してリストにしてくれます。フィルターのかけ方は、

#url article_list?search=学生時代

という風にurlで指定すると、"学生時代"がタイトルか概要にあるものだけがリストになります。

これは便利ですが、"学生時代"がタイトルか概要にある かつ "技術"カテゴリーに分類されている かつ "有料購読"である という風に 2つ、3つ・・・とフィルターをかけたくなることも多々ありますが上記の基本フィルターだけだと実装できません(多分。できるかもしれませんが、自分が知らないだけかも・・・^^; )

ということで自分が見つけた方法は、下記のように実装すると動きます。

実例

api.views
#url article_list とします

class ArticleListAPIView(ListAPIView):
    permission_classes = [AllowAny]
    queryset = Article.objects.all()
    serializer_class = ArticleListSerializer
    filter_backends= [SearchFilter]
    search_fields = ['title',
                     'article_description',
                    ]

    def get_queryset(self, *args, **kwargs):
        queryset_list = Article.objects.all()
        query_f = self.request.GET.get("f")
        query_s = self.request.GET.get("s")
        if query_f:
            queryset_list = queryset_list.filter(
                    Q(first_category__id__contains=query_f)
                    ).distinct()
        if query_s:
            queryset_list = queryset_list.filter(
                    Q(second_category__id__contains=query_s)
                    ).distinct()
        return queryset_list

という感じにすると、"技術"カテゴリーが1stカテゴリーリストの1"有料購読"が別の2ndカテゴリーリストの2に入っているとします。

すると"学生時代"がタイトルか概要にある かつ "技術"カテゴリーに分類されている かつ "有料購読"であるもののリストは、

#url article_list?search=学生時代&f=1&s=2

とかけば出てきます。これは色々応用が効きそうです^^