I am trying to figure out how to filter a ManyToMany field by value. In Django, it is as simple as queryset.filter(m2mfield__name), but I can't quite figure out what I am missing. I am using the Django Rest Framework, and the DjangoFilterBackend.
Models:
class City(models.Model):
name = models.CharField(max_length=80)
class State(models.Model):
name = models.CharField(max_length=50)
cities = models.ManyToManyField(City)
Filters:
import django_filters
class StateFilter(django_filters.FilterSet):
cities = django_filters.CharFilter(
name='cities__name',
lookup_type='contains',
)
class Meta:
model = State
fields = ('name', 'cities')
Serializers:
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
fields = ('name', )
class StateSerializer(serializers.ModelSerializer):
cities = CitySerializer(many=True)
class Meta:
model = State
fields = ('name', 'cities')
filter_class = StateFilter
View:
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .serializers import StateSerializer
class StateList(ListAPIView):
queryset = State.objects.all()
serializer_class = StateSerializer
filter_fields = ('name', 'cities')
The output for ../api/states/ is currently:
[
"name": "Florida",
"cities": [
"name": "Tampa",
"name": "St. Petersburg",
"name": "Orlando"
],
"name": "North Carolina",
"cities": [
"name": "Raleigh",
"name": "Charlotte",
"name": "Greensboro"
]
]
How can I filter the cities via a GET call by name such as:
../api/states/?cities=Charlotte
The result of the above should be:
[
"name": "North Carolina",
"cities": [
"name": "Raleigh",
"name": "Charlotte",
"name": "Greensboro"
]
]
The simplest way to filter the queryset of any view that subclasses GenericAPIView is to override the .get_queryset() method. Overriding this method allows you to customize the queryset returned by the view in a number of different ways.
Well, I found out what I was doing wrong. It was in the view. I had not declared filter_class on the view:
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .serializers import StateSerializer
from .filters import StateFilter
class StateList(ListAPIView):
queryset = State.objects.all()
serializer_class = StateSerializer
filter_fields = ('name', 'cities')
filter_class = StateFilter # This was missing
I accidentally placed it on the serializer instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With