Как добавить множество полей в фильтр поиска в django
Я написал API поиска для своего сайта на фреймворке django rest.
Это API, в котором вы можете задать некоторые параметры в url и получить результат поиска. что мне нужно, так это возможность поиска по жанрам. Это означает, что мне нужно, чтобы API позволяло выполнять поиск типа /api/search/?search=1&search_fields=filmGenre. но сейчас, если я отправляю запрос на этот url, я получаю ошибку FieldKey со следующим сообщением: Related Field got invalid lookup: icontains
вот мой код:
# models.py
class Film(models.Model):
filmID = models.AutoField(primary_key=True)
title = models.CharField(max_length=150)
duration = models.PositiveIntegerField()
typeOf = models.IntegerField(validators=[MaxValueValidator(3), MinValueValidator(1),])
rating = models.FloatField(default=0, validators=[MaxValueValidator(10), MinValueValidator(0),])
releaseDate = models.DateTimeField(null=True)
filmGenre = models.ManyToManyField(Genre)
class Genre(models.Model):
genreID = models.AutoField(primary_key=True)
nameOf = models.CharField(max_length=100, unique=True)
# serializers.py
class FilmSerializer(serializers.ModelSerializer):
class GenreFilmSerializer(serializers.ModelSerializer):
class Meta:
model = Genre
fields = ('nameOf', 'genreID',)
read_only_fields = ('nameOf', 'genreID',)
class CelebrityFilmSerializer(serializers.ModelSerializer):
class Meta:
model = Celebrity
fields = ('nameOf', 'celebID',)
read_only_fields = ('nameOf', 'celebID',)
filmGenre = GenreFilmSerializer(read_only=True, many=True)
filmActor = CelebrityFilmSerializer(read_only=True, many=True)
filmDirector = CelebrityFilmSerializer(read_only=True, many=True)
class Meta:
model = Film
fields = [
"filmID", "title", "price", "duration", "typeOf", "numberOfFilminoRatings",
"filminoRating", "rating", "releaseDate", "detailsEn", "salePercentage",
"saleExpiration", "posterURL", "posterDirectory", 'filmGenre', 'filmActor', 'filmDirector'
]
# views.py
'''Override get_search_fields method of SearchFilter'''
class DynamicSearch(filters.SearchFilter,):
def get_search_fields(self,view, request):
return request.GET.getlist('search_fields',[])
'''Override page_size_query_param attribute of PageNumberPagination'''
class CustomizePagination(PageNumberPagination):
page_size_query_param = 'limit'
"""Pagination Handler"""
class PaginationHanlerMixin(object):
@property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator =None
else :
self._paginator = self.pagination_class()
else :
pass
return self._paginator
def paginate_queryset(self,queryset):
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)
def get_paginated_response(self,data):
if self.paginator is None:
raise "Paginator is None"
return self.paginator.get_paginated_response(data)
class SearchFilm(APIView,PaginationHanlerMixin):
authentication_classes = ()
permission_classes = (AllowAny,)
def __init__(self,):
APIView.__init__(self)
self.search_class=DynamicSearch
self.pagination_class=CustomizePagination
def filter_queryset(self,queryset):
filterd_queryset=self.search_class().filter_queryset(self.request,queryset,self)
return filterd_queryset
def order_list(self,queryset,param):
field=param.split('_')[0]
sorting=param.split('_')[1]
if sorting=='asc':
return queryset.order_by(field)
elif sorting=='desc':
return queryset.order_by(field).reverse()
def get(self, request):
films= Film.objects.all()
filtered_queryset=self.filter_queryset(films)
order_field=request.query_params.get('order_by',None)
if order_field is not None:
filtered_queryset=self.order_list(filtered_queryset,order_field)
#Get appropriate results for each page
results=self.paginate_queryset(filtered_queryset)
if(results is not None):
serializer=FilmSerializer(results,many=True)
serializer=self.get_paginated_response(serializer.data)
else :
serializer=FilmSerializer(filtered_queryset,many=True)
return Response(serializer.data, status=status.HTTP_200_OK)