DRF có 3 filter backend chuẩn, bật ở DEFAULT_FILTER_BACKENDS rồi khai báo trên viewset là xong, không phải tự viết logic query param.
# settings.py
INSTALLED_APPS = [..., 'django_filters']
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter',
],
}
# views.py
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filterset_fields = ['status', 'author'] # ?status=published&author=12
search_fields = ['title', 'body'] # ?search=django
ordering_fields = ['created_at', 'views'] # ?ordering=-views
ordering = ['-created_at'] # defaultCần filter phức tạp (range, custom lookup) thì khai báo FilterSet class riêng:
import django_filters
class PostFilter(django_filters.FilterSet):
min_views = django_filters.NumberFilter(field_name='views', lookup_expr='gte')
created_after = django_filters.IsoDateTimeFilter(field_name='created_at', lookup_expr='gte')
class Meta:
model = Post
fields = ['status', 'author']
class PostViewSet(viewsets.ModelViewSet):
filterset_class = PostFilterSearchFilter mặc định dùng icontains trên field liệt kê — trên bảng to là seq scan chậm.
Production search nghiêm túc nên dùng Postgres FTS (SearchVector / SearchQuery) hoặc Elasticsearch/Meilisearch chứ đừng phụ thuộc SearchFilter cho dataset lớn.
DRF has three standard filter backends; enable them in DEFAULT_FILTER_BACKENDS and declare on the viewset — no need to hand-roll query param logic.
# settings.py
INSTALLED_APPS = [..., 'django_filters']
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter',
],
}
# views.py
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filterset_fields = ['status', 'author'] # ?status=published&author=12
search_fields = ['title', 'body'] # ?search=django
ordering_fields = ['created_at', 'views'] # ?ordering=-views
ordering = ['-created_at'] # defaultFor complex filters (ranges, custom lookups) → use a dedicated FilterSet class:
import django_filters
class PostFilter(django_filters.FilterSet):
min_views = django_filters.NumberFilter(field_name='views', lookup_expr='gte')
created_after = django_filters.IsoDateTimeFilter(field_name='created_at', lookup_expr='gte')
class Meta:
model = Post
fields = ['status', 'author']
class PostViewSet(viewsets.ModelViewSet):
filterset_class = PostFilterPitfall: SearchFilter defaults to icontains on the listed fields → on large tables that is a seq scan and slow.
For serious production search, use Postgres FTS (SearchVector/SearchQuery) or Elasticsearch/Meilisearch — do not rely on SearchFilter for big datasets.