Как добавить несколько фильтров при использовании фреймворка Django Rest search_filter

В настоящее время я пытаюсь создать сайт на основе фуллстэка, используя django для бэкенда. Одной из функций, которую я создаю, является функция поиска. Для этого я использовал встроенный в django-rest SearchFilter, а также встроенный OrderingFilter, чтобы пользователи могли переключать порядок результатов. Однако я также хочу, чтобы пользователи могли фильтровать результаты, например, выбирать конкретный год или конкретное имя из выпадающего меню. То есть, по сути, я хочу иметь возможность использовать фильтр поиска и при этом указать другое поле, которое должно точно соответствовать. Например, допустим, пользователи искали "Cat" и результаты были следующими:


Имя: Cat1
Описание: Счастливый кот
Год: 2017


Имя: Cat2
Описание: Грустный кот
Год: 2017


Имя: Лев
Описание: Крупная кошка
Год: 2018


Имя: Лев
Описание: Крупная кошка
Год: 2019

Все эти результаты отображаются, поскольку содержат "cat" в полях name или description. Но затем я хочу, чтобы пользователь мог указать год через выпадающее меню. Таким образом, меню будет содержать 2017, 2018 и 2019 годы в качестве вариантов, и после выбора 2017 года результаты будут выглядеть следующим образом:


Имя: Cat1
Описание: Счастливый кот
Год: 2017


Имя: Cat2
Описание: Грустный кот
Год: 2017

С отфильтрованными другими годами. Я не могу сделать это на фронт-энде, потому что база данных, с которой я работаю, содержит тысячи записей, что означает, что результаты возвращаются в виде страниц. Эта проблема кажется довольно простой, но ничего из того, что я пробовал, не помогло. Кто-нибудь знает лучший способ решения этой проблемы?

Вот модель базы данных для объектов, по которым ведется поиск:

class Measure(OverrideModel):

year = models.ForeignKey(Year, on_delete=models.PROTECT)
name = models.CharField(max_length=200)
description = models.TextField()

class Meta:
    constraints = [
        models.UniqueConstraint(
            fields=["duration", "code"],
            name=prefix("measure", "duration_code_uniq"),
        )
    ]

А вот текущий вид, который я использую:

class MeasureSearchViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = models.Measure.objects.all()
    serializer_class = serializers.MeasureSerializer
    filter_backends = [OrderingFilter, SearchFilter]
    search_fields = ["name", "description"]
    ordering_fields = ["duration", "name"]

    def get_serializer(self, *args, **kwargs):
        return super().get_serializer(
            *args, program=self.program, tag=False, **kwargs
        )

Любой совет был бы признателен, спасибо :)

Вам необходимо объединить механизмы поиска и фильтрации. Помимо определения search_fields Вам необходимо добавить filter_fields атрибут к Вашему ViewSet:

class MeasureSearchViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = models.Measure.objects.all()
    serializer_class = serializers.MeasureSerializer
    filter_backends = [OrderingFilter, SearchFilter]
    search_fields = ["name", "description"]
    ordering_fields = ["duration", "name"]
    filterset_fields = ['year'] # enable filtering by year

    def get_serializer(self, *args, **kwargs):
        return super().get_serializer(
            *args, program=self.program, tag=False, **kwargs
        )

Подробную информацию можно получить на: https://www.django-rest-framework.org/api-guide/filtering/#generic-filtering

Вернуться на верх