securelms
Engineering
8 min read

Django Rest Framework Filters

H
Hemachandra Routhu
Project Leader
Published On
February 12, 2025

Introduction

Suppose we have a requirement to get records matching a provided date while making a GET call. For example: /weather/?date=2019-06-11.

We can solve this by overriding the get_queryset() in the WeatherView in rest_api/views.py:

views.py
def get_queryset(self):
    date = self.request.query_params.get('date', '')
    if date:
        return Weather.objects.filter(date=date)
    return Weather.objects.all()

The Coupling Problem

This works, but what if tomorrow we want to filter records by the field city? Or state? Every time we add a new field, we have to re-write the get_queryset()method. This is not good programming as it's strongly coupled to specific requirements.

Enter Django-filters

To solve this, we use the django-filter package. First, install it:

terminal
pip install django-filter

Add it to your INSTALLED_APPS and configure the default filter backend in settings.py:

settings.py
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
}

Implementation

Create a FilterSet class in model_filters.py:

model_filters.py
import django_filters
from rest_api.models import Weather

class WeatherFilter(django_filters.FilterSet):
    class Meta:
        model = Weather
        fields = "__all__" # Or ('city', 'state') for specific fields

Update your view to use this filter class:

views.py
class WeatherListView(generics.ListAPIView):
    queryset = Weather.objects.all()
    serializer_class = WeatherSerializer
    filterset_class = model_filters.WeatherFilter

Advanced: Multiple Values

What if the user wants to filter by multiple states? e.g., ?state=California,Texas. We can write a custom method in our filter class:

model_filters.py
class WeatherFilter(django_filters.FilterSet):
    state = django_filters.CharFilter(method='char_filter')

    def char_filter(self, qs, field_name, value):
        value_lst = value.split(',')
        return qs.filter(state__in=value_lst)

Conclusion

Using Django-filters allows for clean, decoupled, and highly maintainable filtering logic in your REST APIs. You can find more details in the official documentation or my GitHub profile.

Have a great day!

Spread the Word
Browse More Articles