By referring to this article, I was able to implement the method of and
search.
Django-filter with DRF - How to do 'and' when applying multiple values with the same lookup?
I want to know how to do or
search for multiple keywords using the same field. How can I implement it?
Here is the code:
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):
# value is either a list or an 'empty' 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')
# title = MultiValueCharFilter(lookup_expr='contains', conjoined=False) -> get an error
class Meta:
model = BookInfo
fields = ['title']
class BookInfoAPIView(viewsets.ReadOnlyModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_class = BookInfoFilter
if I set conjoined=False
like this title = MultiValueCharFilter(lookup_expr='contains', conjoined=False)
get an error __init__() got an unexpected keyword argument 'conjoined'
Django 3.2.5
django-filter 2.4.0
djangorestframework 3.12.4
Python 3.8.5
You can try to modify the queryset returned from MultiValueCharFilter and combine values with operator.
example:
import operator
from functools import reduce
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']