簡體   English   中英

如何在 Django REST 框架 API 響應中使用多標簽過濾器?

[英]How do I use multi tag filters in Django REST Framework API response?

首先,如果我沒有用更好的詞來問問題,我深表歉意。 我正在構建 DRF 應用程序,我有Products Model、 ProductSerializerProductsSummaryView 此外,我有 Workspace Model(不打算談論它,因為它與問題無關)。 現在,我想在成功響應中返回那些附加在特定工作區的產品詳細信息,並根據某些參數進行過濾。

我做了什么:我定義filterset_fieldsfilter_backends 它工作正常。 例如,如果我 go 到這個 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 Model 是:

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

誰能幫助我,讓我知道我需要做什么才能實現所需的功能?

更新:我創建了filters.py文件如下:

# filters.py

import django_filters
from .models import Product

class ProductFilter(django_filters.FilterSet):
    fzg_segment__title = django_filters.CharFilter(field_name="fzg_segment__title", lookup_expr='in')
    parts_group__title = django_filters.CharFilter(field_name="parts_group__title", lookup_expr='in')
    car_brand__title = django_filters.CharFilter(field_name="car_brand__title", lookup_expr='in')
    part__title = django_filters.CharFilter(field_name="part__title", lookup_expr='in')
    country__title = django_filters.CharFilter(field_name="country__title", lookup_expr='in')
    manufacturer__title = django_filters.CharFilter(field_name="manufacturer__title", lookup_expr='in')

    class Meta:
        model = Product
        fields = [
            "fzg_segment__title",
            "parts_group__title",
            "car_brand__title",
            "part__title",
            "country__title",
            "manufacturer__title",
        ]

並且我更新了我的views.py如下:

# views.py

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_class = filters.ProductFilter

    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)
        queryset = workspace.products.all()
        queryset = self.filter_queryset(queryset)
        return queryset

我嘗試在 URL 中使用如下過濾器:

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

`{{domain]]/path/?country__title__in=Japan&country__title__in=Korea``

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

{{domain]]/path/?country__title[]=Japan&country__title[]=Korea

但一切都是徒勞的,我什至無法使用單個過濾器,留下多個過濾器。 我做錯了什么?

要根據 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 查詢參數中使用 in 查找類型,以根據多個值過濾查詢集。 例如,要過濾標題為“日本”和“韓國”的產品的查詢集,您可以使用以下 URL:

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

或者,您也可以在過濾器集中使用 Django-filter 提供的 MultipleChoiceFilter 以允許對特定字段的多個值進行過濾。

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 = filters.CharInFilter(field_name="country__title", lookup_expr='in')
    

參數 url 如: /?country=Japan,Korea

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM