Mastering DjangoFilterBackend in Django Rest Framework
Last updated 1 month, 1 week ago | 139 views 75 5

Filtering is one of the most common and essential features in any API. Whether you're narrowing down a list of blog posts by author or fetching products under a certain price, filtering makes your APIs powerful and flexible.
Django Rest Framework (DRF) provides excellent filtering support via DjangoFilterBackend
, which is built on top of the popular django-filter
package.
What is DjangoFilterBackend
?
DjangoFilterBackend
is a filter backend in DRF that integrates the django-filter
library, allowing you to filter querysets using URL parameters. It supports:
-
Simple field-based filters
-
Complex custom filters
-
Lookups like
lt
,gte
,in
, etc.
Installation and Setup
Step 1: Install django-filter
pip install django-filter
Step 2: Add to INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
...
'django_filters',
]
Step 3: Add to DRF Configuration (Optional)
# settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
Basic Usage
You can enable filtering by adding DjangoFilterBackend
to your view and setting the filterset_fields
.
Example ViewSet:
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['category', 'in_stock', 'price']
Example Request:
GET /api/products/?category=electronics&in_stock=true&price__lt=500
This filters products by category, availability, and price.
Using Custom FilterSet
Class
If you want more control (like filtering by ranges, custom logic, or using multiple field lookups), define a FilterSet
.
filters.py:
import django_filters
from .models import Product
class ProductFilter(django_filters.FilterSet):
price_min = django_filters.NumberFilter(field_name="price", lookup_expr='gte')
price_max = django_filters.NumberFilter(field_name="price", lookup_expr='lte')
name = django_filters.CharFilter(lookup_expr='icontains')
class Meta:
model = Product
fields = ['category', 'in_stock', 'price_min', 'price_max', 'name']
views.py:
from .filters import ProductFilter
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = ProductFilter
Example Request:
GET /api/products/?price_min=100&price_max=1000&name=phone
✅ Full Example
models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
category = models.CharField(max_length=50)
price = models.DecimalField(max_digits=10, decimal_places=2)
in_stock = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
filters.py
import django_filters
from .models import Product
class ProductFilter(django_filters.FilterSet):
price_min = django_filters.NumberFilter(field_name="price", lookup_expr='gte')
price_max = django_filters.NumberFilter(field_name="price", lookup_expr='lte')
class Meta:
model = Product
fields = ['category', 'in_stock', 'price_min', 'price_max']
views.py
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from .models import Product
from .serializers import ProductSerializer
from .filters import ProductFilter
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = ProductFilter
Tips and Best Practices
Tip | Reason |
---|---|
✅ Use filterset_class for complex filtering |
Cleaner code and more control |
✅ Name custom filters clearly (e.g., price_min ) |
Improves API usability |
✅ Index frequently filtered fields in the DB | Improves performance |
✅ Document available filters | Helps API consumers |
✅ Combine with pagination and ordering | For robust API endpoints |
⚠️ Common Pitfalls
Pitfall | Solution |
---|---|
❌ Filters not working | Ensure DjangoFilterBackend is in filter_backends |
❌ Error on unknown filter field | DRF throws a 400; whitelist fields using filterset_fields or Meta.fields |
❌ Poor performance on large datasets | Add DB indexes, optimize queries |
❌ Typos in query params | Use clear, predictable field names |
Combine with Other Backends
You can combine DjangoFilterBackend
with other backends like:
from rest_framework.filters import SearchFilter, OrderingFilter
filter_backends = [
DjangoFilterBackend,
SearchFilter,
OrderingFilter
]
Conclusion
DjangoFilterBackend
is one of the most useful tools in Django Rest Framework for building dynamic and customizable APIs. Whether you want simple filters or advanced custom logic, django-filter
has you covered.
With clean separation between views and filter logic, it helps you keep code organized while delivering robust filtering capabilities to your API consumers.