#django-rest-framework #filtering #django-rest-viewsets
#django-rest-framework #фильтрация #django-rest-viewsets
Вопрос:
У меня есть модель, которую я хочу отфильтровать по нескольким значениям.
моя модель:
class Product(models.Model):
ean = models.CharField(max_length=13, unique=True)
product_id = models.CharField(max_length=20, null=True, blank=True)
product_image = models.URLField(max_length=300, null=True, blank=True)
product_title = models.CharField(max_length=300, null=True, blank=True)
Я либо хочу фильтровать по полю ‘ean’, либо по первичному ключу, оба будут работать. С моей текущей настройкой я вижу только последнее значение. Например, когда я создаю URL-адрес как www.example.com/api/Product/?id=1amp;id=2 , я вижу только продукт с идентификатором 2, и я хочу видеть продукт с идентификатором 1 и с идентификатором 2.
Как я должен создать свой ViewSet? В настоящее время у меня есть:
class ProductViewSet(ModelViewSet):
queryset = models.Product.objects.all()
serializer_class = serializers.ProductSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = ('id','ean')
Комментарии:
1. Используйте класс filterset, который даст вам больше контроля над операциями фильтрации
2. Не могли бы вы привести пример @ArakkalAbu?
Ответ №1:
Существует еще более простой способ добиться этого с помощью django-filter
пакета. В глубине django-filter
документации упоминается, что вы можете использовать «словарь имен полей, сопоставленных со списком поисковых запросов».
Ваш код будет обновлен следующим образом:
# views.py
from django_filters.rest_framework import DjangoFilterBackend
class ProductViewSet(ModelViewSet):
queryset = models.Product.objects.all()
serializer_class = serializers.ProductSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = {
'id': ["in", "exact"], # note the 'in' field
'ean': ["exact"]
}
Теперь в URL-адресе, который вы добавите __in
в фильтр, прежде чем предоставить свой список параметров, и он будет работать так, как вы ожидаете:
www.example.com/api/Product/?id__in=1,2
django-filter
Документация о том, какие фильтры поиска доступны, довольно скудная, но in
фильтр поиска упоминается в самой документации Django.
Ответ №2:
Вы можете попробовать что-то подобное в своем views.py
и передать свои ключи id
и ean
параметры. Обратите внимание, что вы должны передавать несколько значений в виде значений, разделенных запятыми, в параметрах.
class ProductViewSet(APIView):
def get(self, request):
_id = self.request.GET.get('id', None).split(',')
ean = self.request.GET.get('ean', None).split(',')
qs = Product.objects.filter(Q(id__in=_id) | Q(ean__in=ean))
data = serializers.ProductSerializer(qs, many=True, context={'request': request}).data
if data:
return Response({
'message': 'success',
"data":data,
},status=200)
else:
return Response({
'message':'no data available',
'success':'False'
},status=200)