Как использовать мультитеговые фильтры в ответе API Django REST Framework?

Прежде всего, я извиняюсь, если я не задал вопрос, используя лучшие слова. Я создаю приложение DRF, у меня есть Products Модель, ProductSerializer и ProductsSummaryView. Кроме того, у меня есть Workspace Model (не буду говорить об этом, так как это не относится к вопросу). Теперь я хочу возвращать в ответе success те данные о товарах, которые привязаны к определенному рабочему пространству, отфильтрованные по некоторым параметрам

Что я сделал: Я определил filterset_fields и filter_backends. Все работает нормально. Например, если я перейду по этому URL {{domain}}/path/?country__title=Japan, он отфильтрует данные по Японии и покажет их мне. Но проблема в том, что я хочу фильтровать, используя мульти-тег, например, если я хочу увидеть детали для Японии и Кореи, то я хочу что-то вроде этого {{domain}}/path/?country__title=Japan&country__title=Korea, но это не работает, и он просто возвращает все детали. Я даже попробовал добавить формат пустого списка в URL и попробовал этот URL {{domain}}/path/?country__title[]=Japan&country__title[]=Korea, но он все равно не работает.

Может ли кто-нибудь помочь мне в этом?

Моя Product модель:

class Product(BaseModel):
    """Product model to store all prices of a product and
    related brand and countries it's available in"""
    product = models.CharField(max_length=255)
    country = models.ForeignKey(Country, null=True, on_delete=models.DO_NOTHING)
    car_brand = models.ForeignKey(
        CarBrand, on_delete=models.DO_NOTHING, null=True, blank=True
    )
    part = models.ForeignKey(Part, null=True, blank=True, on_delete=models.DO_NOTHING)
    fzg_segment = models.ForeignKey(
        FZGSegment, on_delete=models.DO_NOTHING, null=True, blank=True
    )
    parts_group = models.ForeignKey(
        PartsGroup, on_delete=models.DO_NOTHING, null=True, blank=True
    )
    last_collected = models.DateField(null=True, blank=True)
    usage_recommendation = models.CharField(max_length=255)
    recommended_action = models.CharField(max_length=255)
    recommended_action_value = models.DecimalField(max_digits=6, decimal_places=2)
    recommended_price = models.DecimalField(max_digits=6, decimal_places=2)
    rrp = models.DecimalField(max_digits=6, decimal_places=2)
    iam_price = models.DecimalField(max_digits=6, decimal_places=2)
    currency = models.ForeignKey(
        Currency, null=True, blank=True, on_delete=models.DO_NOTHING
    )
    iam_index = models.DecimalField(max_digits=6, decimal_places=2)
    factor = models.DecimalField(max_digits=6, decimal_places=2)
    items_count = models.PositiveIntegerField(default=0)
    manufacturer = models.ForeignKey(
        Manufacturer, on_delete=models.DO_NOTHING, null=True, blank=True
    )
    is_in_stock = models.BooleanField(default=True)
    added_at = models.DateField(null=True, blank=True)
    last_in_stock = models.DateField(null=True, blank=True)
    last_searched_at = models.DateField(null=True, blank=True)
    avg_in_stock = models.DecimalField(
        null=True, blank=True, max_digits=6, decimal_places=2
    )

    def __str__(self):
        return self.product

Мой ProductSerializer сериализатор:

class ProductSerializer(serializers.ModelSerializer):
    """Serializer for the part object"""
    parts_group = PartsGroupSerializer()
    fzg_segment = FZGSegmentSerializer()

    class Meta:
        model = Product
        fields = (
            "id",
            "product",
            "fzg_segment",
            "parts_group",
            "last_collected",
            "usage_recommendation",
            "recommended_action",
            "recommended_action_value",
            "recommended_price",
            "rrp",
            "iam_price",
            "iam_index",
            "factor",
            "items_count",
        )
        read_only_fields = ("id",)

А мой ProductsSummaryView API:

class ProductsSummaryView(mixins.ListModelMixin, viewsets.GenericViewSet):
    """Viewset to return data for products in a workspace"""
    serializer_class = serializers.ProductSerializer
    permission_classes = (permissions.IsWorkspaceAdminPermission,)
    pagination_class = StandardSetPagination
    filter_backends = [DjangoFilterBackend]
    filterset_fields = [
        "fzg_segment__title",
        "parts_group__title",
        "car_brand__title",
        "usage_recommendation",
        "recommended_action",
    ]

    def get_queryset(self) -> models.Product:
        """Returns queryset of all the products of a workspace"""
        workspace = self.kwargs["workspace"]
        workspace = get_object_or_404(models.Workspace, pk=workspace)
        return workspace.products.all()

Может ли кто-нибудь помочь мне и сообщить, что мне нужно сделать, чтобы достичь желаемой функциональности?

Для фильтрации набора запросов на основе нескольких значений определенного поля в Django Rest Framework (DRF) вы можете использовать тип поиска in в вашем наборе фильтров. Чтобы использовать этот тип поиска, вам нужно обновить поля вашего набора фильтров, включив в них тип поиска in следующим образом:

class ProductFilter(filters.FilterSet):
    country__title = filters.CharFilter(field_name='country__title', lookup_expr='in')
    
    class Meta:
        model = Product
        fields = ['country__title']

После этого набора фильтров вы можете использовать тип поиска в параметрах запроса URL для фильтрации набора запросов на основе нескольких значений. Например, чтобы отфильтровать набор запросов для продуктов со странами "Япония" и "Корея", вы можете использовать следующий URL:

{{domain}}/path/?country__title__in=Japan,Korea

Альтернативно, вы также можете использовать MultipleChoiceFilter, предоставляемый Django-filter в вашем наборе фильтров, чтобы позволить фильтрацию по нескольким значениям для определенного поля.

class ProductFilter(filters.FilterSet):
    country__title = filters.MultipleChoiceFilter(field_name='country__title')
    
    class Meta:
        model = Product
        fields = ['country__title']

С помощью этого набора фильтров вы можете использовать следующий URL для фильтрации набора запросов для продуктов со странами "Япония" и "Корея":

{{domain}}/path/?country__title=Japan&country__title=Korea

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

from django_filters.filters import BaseInFilter
from django_filters import rest_framework as filters

class CharInFilter(BaseInFilter, filters.CharFilter):
    pass


class ProductFilterSet(filters.FilterSet):
    country = CharInFilter(field_name="country__title", lookup_expr='in')

    class Meta:
        model = Product
        fields = ["country"]
    

Урл параметров выглядит следующим образом: /?country=Japan,Korea

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