在DRF中过滤字段的多个值

时间:2020-07-14 09:12:33

标签: django django-rest-framework django-filter

在Amazon中,您可以按多个品牌进行过滤,例如。您选择耐克,彪马,阿迪达斯。发送回的查询集包含属于这些品牌之一的产品。

如果您有以下模型:

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    brand = models.CharField(max_length=100)

类似的串行器:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Product
        fields = "__all__"

像这样的视图集:

class ProductViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.ProductSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [filters.ProductMultipleFilterBackend ]

filters.py文件:

from rest_framework import filters as drf_filters
from django_filters import rest_framework as df_filters

class MultipleField(MultipleChoiceField):
    def valid_value(self, value):   
        return True

class MultipleFilter(df_filters.MultipleChoiceFilter):
    field_class = MultipleField

class ProductMultipleFilterBackend(df_filters.FilterSet):
    brand = MultipleFilter(lookup_expr="icontains", field_name = "brand")
    search = MultipleFilter(lookup_expr="icontains", field_name = "description")

    class Meta:
        model = models.Product
        fields = ["brand", "search"]

上面的代码是我发现的here。但这大约5岁了,也许我肯定不知道有更好的方法,并且在代码上出现以下错误:

filter_queryset() takes 2 positional arguments but 4 were given

这些请求的网址结构是什么: / someurl?brand =耐克,阿迪达斯,彪马 要么 / someurl?brand = [耐克,阿迪达斯,彪马]

预先感谢!!!!

1 个答案:

答案 0 :(得分:1)

multiple choice的正常行为类似于?f=v1&f=v2,而您可以通过使用widget来传递正确的CSVWidget来将默认网址结构更改为逗号分隔值

from django_filters.fields import CSVWidget

class ProductMultipleFilterBackend(df_filters.FilterSet):
    brand = MultipleFilter(
                 lookup_expr="icontains", 
                 field_name = "brand",
                 widget=CSVWidget
            )
     ...

然后,您可以使用csv格式进行过滤,例如:url?brand=a,b