Фильтр по нескольким значениям в Django Rest Framework

#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)