この記事では、 Django-filterを利用する際に、複数キーワードのand
,or
検索に対応させる方法を紹介します。
◆動作検証環境
・ローカル環境:mac Catalina
・python:3.7.5
・Django:3.1.2
・DjangoRESTframework: 3.12.1
・python:3.7.5
・Django:3.1.2
・DjangoRESTframework: 3.12.1
スポンサードリンク
【Django-filter with DRF】複数キーワードのand
検索
1つのキーワードに対する検索の条件をつける場合は、CharFilter の利用で対応できますが、複数のand検索の場合はカスタムフィルターを作成する必要があります。
以下のコードにする事でand検索が可能となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from rest_framework import viewsets from django_filters import rest_framework as filters from .serializers import BookInfoSerializer from .models import BookInfo class MultiValueCharFilter(filters.BaseCSVFilter, filters.CharFilter): def filter(self, qs, value): values = value or [] for value in values: qs = super(MultiValueCharFilter, self).filter(qs, value) return qs class BookInfoFilter(filters.FilterSet): title = MultiValueCharFilter(lookup_expr='contains') class Meta: model = BookInfo fields = ['title'] class BookInfoAPIView(viewsets.ReadOnlyModelViewSet): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer filter_class = BookInfoFilter |
【Django-filter with DRF】複数キーワードのor
検索
or検索の場合、さきほど紹介したand検索のコードと、MultipleChoiceFilterの方法を参考にし、以下のようにしてもうまく機能しません。
1 2 3 | title = MultiValueCharFilter(lookup_expr='contains', conjoined=False) |
対応するために、以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import operator from functools import reduce from django.db.models import Q class MultiValueCharFilter(BaseCSVFilter, CharFilter): def filter(self, qs, value): expr = reduce( operator.or_, (Q(**{f'{self.field_name}__{self.lookup_expr}': v}) for v in value) ) return qs.filter(expr) class BookInfoFilter(filters.FilterSet): title = MultiValueCharFilter(lookup_expr='contains') class Meta: model = BookInfo fields = ['title'] |
この記事では、 Django-filterを利用する際に、複数キーワードのand
,or
検索に対応させる方法を紹介しました。