How do you use the django-filter package with a list of parameters?
I found the following solution for my problem :)
https://gist.github.com/aBuder/654fb945f085b17358d8
from webapp.serializers import *from rest_framework import viewsetsfrom rest_framework import filtersfrom django_filters import Filter, FilterSetclass ListFilter(Filter): def filter(self, qs, value): if not value: return qs # For django-filter versions < 0.13, use lookup_type instead of lookup_expr self.lookup_expr = 'in' values = value.split(',') return super(ListFilter, self).filter(qs, values)class AccommodationFilter(FilterSet): ids = ListFilter(name='id') accommodationType_ids = ListFilter(name='accommodationType_id') class Meta: model = Accommodation fields = ['ids', 'accommodationType_ids']class AccommodationViewSet(viewsets.ReadOnlyModelViewSet): """ REST API endpoint for 'accommodation' resource """ queryset = Accommodation.objects.all() serializer_class = AccommodationSerializer filter_backends = (filters.DjangoFilterBackend,) filter_class = AccommodationFilter
I know it is an old question, but might be worth it to give an updated answer.
Django-filter contributors have added a field called BaseInFilter
which you can combine with other filters to validate the content.
See the docs:https://django-filter.readthedocs.io/en/latest/ref/filters.html#baseinfilter
For example, this would work in your case:
from django_filters import rest_framework as filtersclass NumberInFilter(filters.BaseInFilter, filters.NumberFilter): passclass AccommodationFilter(filters.FilterSet): accommodationType_id_in = NumberInFilter(field_name='accommodationType_id', lookup_expr='in') class Meta: model = Accommodation fields = ['accommodationType_id_in', ]
Then you would be able to filter by a list of ids: http://localhost:8000/accommodations?accommodationType_id_in=1,2
Now there is an even simpler way to achieve this. Deep within the django-filter
documentation, it mentions that you can use "a dictionary of field names mapped to a list of lookups".
Your code would be updated like so:
class AccommodationViewSet(viewsets.ReadOnlyModelViewSet): """ REST API endpoint for 'accommodation' resource """ queryset = Accommodation.objects.all() serializer_class = AccommodationSerializer filter_backends = (filters.DjangoFilterBackend,) filter_fields = { 'accommodationType_id': ["in", "exact"], # note the 'in' field 'name': ["exact"] }
Now in the URL you would add __in
to the filter before supplying your list of parameters and it would work as you expect:
http://localhost:8000/accommodations?accommodationType_id__in=1,2
The django-filter
documentation on what lookup filters are available is quite poor, but the in
lookup filter is mentioned in the Django documentation itself.