Filters
1. Basic Setup: Install and Configure Django Filter
Installation:
To use django-filter, install it via pip:
pip install django-filterAdd 'django_filters' to your INSTALLED_APPS in the Django settings.py:
INSTALLED_APPS = [
    # Other apps...
    'django_filters',
]2. Defining a FilterSet Class
A FilterSet is the core class of django-filter. It defines which model fields should be available for filtering.
Example: A Book Model
from django.db import models
class Book(models.Model):
    title = models.CharField(max_length=255)
    author = models.CharField(max_length=100)
    published_date = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)Defining a FilterSet:
import django_filters
from .models import Book
class BookFilter(django_filters.FilterSet):
    class Meta:
        model = Book
        fields = ['author', 'published_date', 'price']3. Using Filters with Django’s Generic Views
Django’s ListView or TemplateView can easily be enhanced with filtering capabilities.
Example: Using Filters in a View
from django.shortcuts import render
from django_filters.views import FilterView
from .models import Book
from .filters import BookFilter
class BookListView(FilterView):
    model = Book
    filterset_class = BookFilter
    template_name = 'books/book_list.html'Displaying the Filter in Templates:
<form method="get">
    {{ filter.form.as_p }}
    <button type="submit">Filter</button>
</form>
<ul>
  {% for book in filter.qs %}
    <li>{{ book.title }} by {{ book.author }}</li>
  {% endfor %}
</ul>4. Using Filters with Django REST Framework (ModelViewSet)
In Django REST Framework (DRF), you can easily integrate filters with your API endpoints using ModelViewSet and the DjangoFilterBackend.
Steps to Enable Filtering in DRF:
- Add django_filtersto DRF Configuration: In yoursettings.pyfile, addDjangoFilterBackendtoDEFAULT_FILTER_BACKENDS:
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}- Create a FilterSet: Using the earlier BookFilterexample:
import django_filters
from .models import Book
class BookFilter(django_filters.FilterSet):
    min_price = django_filters.NumberFilter(field_name="price", lookup_expr='gte')
    max_price = django_filters.NumberFilter(field_name="price", lookup_expr='lte')
    class Meta:
        model = Book
        fields = ['author', 'published_date', 'min_price', 'max_price']- Integrate FilterSet with ModelViewSet:
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from .models import Book
from .serializers import BookSerializer
from .filters import BookFilter
class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = BookFilterExample Query Parameters in API:
You can now filter books by passing query parameters like:
/api/books/?author=John&min_price=10&max_price=50This URL filters books written by “John” with a price between 10 and 50.
5. Advanced Filters
Custom Filters:
For more advanced use cases, you can define custom filters. For example, to filter by a date range:
class BookFilter(django_filters.FilterSet):
    date_range = django_filters.DateFromToRangeFilter(field_name="published_date")
    class Meta:
        model = Book
        fields = ['author', 'date_range']Using Different Lookups:
You can apply different lookup expressions, such as: - exact: Matches an exact value. - iexact: Case-insensitive exact match. - contains: Checks if a field contains a substring. - gte: Greater than or equal. - lte: Less than or equal.
class BookFilter(django_filters.FilterSet):
    title_contains = django_filters.CharFilter(field_name="title", lookup_expr='icontains')6. Pagination with Filters
Django Filter works well with Django’s built-in pagination. You can paginate the filtered results in both class-based and function-based views.
Example with Pagination in Function-Based View:
from django.core.paginator import Paginator
def book_list(request):
    books = Book.objects.all()
    filter = BookFilter(request.GET, queryset=books)
    paginator = Paginator(filter.qs, 10)  # Show 10 books per page
    page = request.GET.get('page')
    books = paginator.get_page(page)
    return render(request, 'books/book_list.html', {'filter': filter, 'books': books})7. Performance Considerations
- Large Querysets: Filtering large datasets can be computationally expensive. If you expect heavy use of filters on large datasets, you may want to optimize the queries by adding database indexes on fields being filtered.
- Complex Queries: If your filters are complex (e.g., involving joins across multiple tables), consider writing custom queryset methods or optimizing the queries to improve performance.
8. Best Practices for Django Filters
- Use Filters Sparingly: Avoid overcomplicating views by adding too many filters. Provide users with the most relevant filter options.
- Cache Filter Results: If filtering is used frequently, caching the filtered querysets can greatly improve performance.
- Paginate Large Querysets: Always paginate filtered querysets to avoid slow rendering times on large datasets.
- Combine Filters and Search: For a more flexible user experience, consider combining filters with a search functionality using Django’s Qobjects or a full-text search tool.