Integration with DRF¶
Integration with Django Rest Framework is provided through a DRF-specific FilterSet
and a filter backend. These may be found in the rest_framework
sub-package.
Quickstart¶
Using the new FilterSet
simply requires changing the import path. Instead of importing from django_filters
, import from the rest_framework
sub-package.
from django_filters import rest_framework as filters
class ProductFilter(filters.FilterSet):
...
Your view class will also need to add DjangoFilterBackend
to the filter_backends
.
from django_filters import rest_framework as filters
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ('category', 'in_stock')
If you want to use the django-filter backend by default, add it to the DEFAULT_FILTER_BACKENDS
setting.
# settings.py
INSTALLED_APPS = [
# ...
'rest_framework',
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
# ...
),
}
Adding a FilterSet with filterset_class
¶
To enable filtering with a FilterSet
, add it to the filterset_class
parameter on your view class.
from rest_framework import generics
from django_filters import rest_framework as filters
from myapp import Product
class ProductFilter(filters.FilterSet):
min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')
class Meta:
model = Product
fields = ['category', 'in_stock']
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ProductFilter
Using the filterset_fields
shortcut¶
You may bypass creating a FilterSet
by instead adding filterset_fields
to your view class. This is equivalent to creating a FilterSet
with just Meta.fields.
from rest_framework import generics
from django_filters import rest_framework as filters
from myapp import Product
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ('category', 'in_stock')
# Equivalent FilterSet:
class ProductFilter(filters.FilterSet):
class Meta:
model = Product
fields = ('category', 'in_stock')
Note that using filterset_fields
and filterset_class
together is not
supported.
Overriding FilterSet creation¶
FilterSet
creation can be customized by overriding the following methods on the backend class:
.get_filterset(self, request, queryset, view)
.get_filterset_class(self, view, queryset=None)
.get_filterset_kwargs(self, request, queryset, view)
You can override these methods on a case-by-case basis for each view, creating unique backends, or these methods can be used to write your own hooks to the view class.
class MyFilterBackend(filters.DjangoFilterBackend):
def get_filterset_kwargs(self, request, queryset, view):
kwargs = super().get_filterset_kwargs(request, queryset, view)
# merge filterset kwargs provided by view class
if hasattr(view, 'get_filterset_kwargs'):
kwargs.update(view.get_filterset_kwargs())
return kwargs
class BookFilter(filters.FilterSet):
def __init__(self, *args, author=None, **kwargs):
super().__init__(*args, **kwargs)
# do something w/ author
class BookViewSet(viewsets.ModelViewSet):
filter_backends = [MyFilterBackend]
filterset_class = BookFilter
def get_filterset_kwargs(self):
return {
'author': self.get_author(),
}
Crispy Forms¶
If you are using DRF’s browsable API or admin API you may also want to install django-crispy-forms
, which will enhance the presentation of the filter forms in HTML views, by allowing them to render Bootstrap 3 HTML. Note that this isn’t actively supported, although pull requests for bug fixes are welcome.
pip install django-crispy-forms
With crispy forms installed and added to Django’s INSTALLED_APPS
, the browsable API will present a filtering control for DjangoFilterBackend
, like so:
Additional FilterSet
Features¶
The following features are specific to the rest framework FilterSet:
BooleanFilter
’s use the API-friendlyBooleanWidget
, which accepts lowercasetrue
/false
.Filter generation uses
IsoDateTimeFilter
for datetime model fields.Raised
ValidationError
’s are reraised as their DRF equivalent.