Understanding filter_backends in Django Rest Framework

Last updated 1 month, 1 week ago | 110 views 75     5

Tags:- Python Django DRF

Filtering is a core part of building powerful, dynamic, and user-friendly APIs. Django Rest Framework (DRF) makes this easy using filter_backends, which allow you to control how querysets are filtered based on request parameters.

This article covers:

  • What filter_backends are

  • Built-in filter backends

  • How to enable and use them

  • A complete example

  • Tips and common pitfalls


What Are filter_backends?

In DRF, filter_backends are classes that implement logic to modify the queryset returned by a view, based on request parameters. These are applied after authentication and permission checks but before pagination.

You can specify one or more backends to customize your filtering behavior.


⚙️ Commonly Used Built-in Filter Backends

1. DjangoFilterBackend

Uses django-filter to provide powerful, declarative filtering.

from django_filters.rest_framework import DjangoFilterBackend

2. SearchFilter

Allows basic search over specified fields.

from rest_framework.filters import SearchFilter

3. OrderingFilter

Enables sorting of results by specified fields.

from rest_framework.filters import OrderingFilter

Step-by-Step: Using filter_backends

Step 1: Install django-filter (if using DjangoFilterBackend)

pip install django-filter

Add to INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    ...
    'django_filters',
]

Step 2: Configure DRF to Use Filter Backends Globally (Optional)

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
        'rest_framework.filters.OrderingFilter',
    ]
}

Step 3: Use in Your View or ViewSet

from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from .models import Post
from .serializers import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['author', 'category']
    search_fields = ['title', 'content']
    ordering_fields = ['created_at', 'title']

✅ Complete Example

models.py

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.CharField(max_length=50)
    category = models.CharField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)

serializers.py

from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = '__all__'

views.py

from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['author', 'category']
    search_fields = ['title', 'content']
    ordering_fields = ['created_at', 'title']

Example Query Usage

Filter by field:

GET /api/posts/?author=alice&category=tech

Search by keyword:

GET /api/posts/?search=django

Order results:

GET /api/posts/?ordering=-created_at

Tips & Best Practices

Tip Why It Helps
✅ Use filterset_fields for simple filtering DRF auto-generates filters
✅ Use filterset_class for complex filters Customize behavior with FilterSet
✅ Combine filters for powerful querying Search + filter + order = great UX
✅ Document available filter params Helps API consumers
✅ Set defaults globally Cleaner code in views

⚠️ Common Pitfalls

Pitfall Fix
❌ Filters not working Ensure DEFAULT_FILTER_BACKENDS is set or use filter_backends in views
❌ Forgetting to install django-filter Causes import errors
❌ Filtering on unindexed fields Can lead to performance issues
❌ Forgetting to define search_fields or ordering_fields Makes search and ordering ineffective

Custom Filter Backends

You can also build your own filter backend by extending BaseFilterBackend.

from rest_framework.filters import BaseFilterBackend

class MyCustomFilterBackend(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        if 'active' in request.query_params:
            return queryset.filter(is_active=True)
        return queryset

Add to your view:

filter_backends = [MyCustomFilterBackend]

Conclusion

filter_backends in Django Rest Framework give you the flexibility to build robust, user-friendly, and performant APIs. Whether you need simple field filtering, full-text search, or advanced sorting, DRF has you covered — and when it doesn't, custom filter backends are easy to implement.