In Amazon you can filter by Multiple Brands, eg. You select Nike, Puma, Adidas. The queryset that is sent back has products which belong to either of those brands.
if you have a model like:
class Product(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
brand = models.CharField(max_length=100)
a serializer like:
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = models.Product
fields = "__all__"
viewset like:
class ProductViewSet(viewsets.ModelViewSet):
serializer_class = serializers.ProductSerializer
permission_classes = [IsAuthenticated]
filter_backends = [filters.ProductMultipleFilterBackend ]
filters.py file:
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"]
the above code was something i found here. But it's like 5 years old and there might be a better way that i surely don't know about and i'm getting the following error on the code:
filter_queryset() takes 2 positional arguments but 4 were given
What would be the url structure for these requests: /someurl?brand=Nike,Adidas,Puma or /someurl?brand=[Nike,Adidas,Puma]
Thanks in Advance !!!!
The normal behavior for multiple choice
is like ?f=v1&f=v2
, while you could pass proper widget
to change the default url structure to comma separated value by using CSVWidget
from django_filters.fields import CSVWidget
class ProductMultipleFilterBackend(df_filters.FilterSet):
brand = MultipleFilter(
lookup_expr="icontains",
field_name = "brand",
widget=CSVWidget
)
...
Then, you could filter using csv format like: url?brand=a,b