Query Parameters & Filtering#
Filtering#
django-filter#
pip install django-filter
# settings.py
INSTALLED_APPS = [
# ...
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
],
}
# views.py
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['is_published', 'author', 'category']
# Usage: GET /api/posts/?is_published=true&author=1
Custom FilterSet#
# filters.py
import django_filters
from .models import Post
class PostFilter(django_filters.FilterSet):
title = django_filters.CharFilter(lookup_expr='icontains')
created_after = django_filters.DateFilter(field_name='created_at', lookup_expr='gte')
views_min = django_filters.NumberFilter(field_name='views', lookup_expr='gte')
class Meta:
model = Post
fields = ['is_published', 'author', 'category']
# views.py
from .filters import PostFilter
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filterset_class = PostFilter
# Usage:
# GET /api/posts/?title=django
# GET /api/posts/?created_after=2024-01-01
# GET /api/posts/?views_min=100
Search#
# views.py
from rest_framework.filters import SearchFilter
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [SearchFilter]
search_fields = ['title', 'content', 'author__username']
# Usage: GET /api/posts/?search=django
# Searches in title, content, and author username
Ordering#
# views.py
from rest_framework.filters import OrderingFilter
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['created_at', 'views', 'title']
ordering = ['-created_at'] # Default ordering
# Usage:
# GET /api/posts/?ordering=created_at
# GET /api/posts/?ordering=-views,title
Manual Filtering#
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
def get_queryset(self):
queryset = Post.objects.all()
# Filter by query param
is_published = self.request.query_params.get('is_published')
if is_published is not None:
queryset = queryset.filter(is_published=is_published.lower() == 'true')
# Search
search = self.request.query_params.get('search')
if search:
queryset = queryset.filter(title__icontains=search)
# Date range
date_from = self.request.query_params.get('date_from')
date_to = self.request.query_params.get('date_to')
if date_from:
queryset = queryset.filter(created_at__gte=date_from)
if date_to:
queryset = queryset.filter(created_at__lte=date_to)
return queryset
Multiple Filters#
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['is_published', 'author']
search_fields = ['title', 'content']
ordering_fields = ['created_at', 'views']
# Usage:
# GET /api/posts/?is_published=true&search=django&ordering=-created_at
Related Field Filtering#
# Filter by related field
class PostFilter(django_filters.FilterSet):
author_username = django_filters.CharFilter(field_name='author__username', lookup_expr='icontains')
category_name = django_filters.CharFilter(field_name='category__name', lookup_expr='icontains')
class Meta:
model = Post
fields = ['author_username', 'category_name']
Next: Pagination