Filter data in Django Rest Framework
Tags: django, djangorestframework, python, filter
Published: 2021-02-19 03:53:24

### 1. Basic setup

Install the `django-filter` using pip,

```bash
pip install django-filter
```

Then add `django_filters` to Django's `INSTALLED_APPS`,

```python
INSTALLED_APPS = [
    ...
    'django_filters',
    ...
]
```

Add the `DEFAULT_FILTER_BACKENDS` setting in Django `settings.py` file as below,

```python
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
```

For this example, I created the `Introduction` model and `IntroductionSerializer` class as below. I am going to develop mainly three functions here, i.e.

1. Filter data functionality based on `name` and `id`(automatically generated field from the Django model, which is treated as the primary key) field

2. Search the data based on `name` and `intro` fields and 

3. Ordering the data based on the `name` field and set default order to `id`

```python
from django.db import models

# Introduction model
class Introduction(models.Model):
    name = models.CharField(max_length=100)
    intro = models.CharField(max_length=1000, blank=True)
    video_link = models.CharField(max_length=100, blank=True)

    def __str__(self):
        return self.name
```

```python
from rest_framework import serializers
from .models import Introduction

class IntroductionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Introduction
        fields = '__all__'
```

Now let's write the `viewset` function to apply the required filters, search, and ordering. I am going to use the ModelViewSet in this tutorial. In `ModelViewSet`, you need to provide at least `queryset` and `serializer_class` attribute. For my case, `queryset` and `serializer_class` attributes will be as below,

```python
from rest_framework.viewsets import ModelViewSet
from .models import Introduction
from .serializers import IntroductionSerializer

# Introduction viewset
class IntroductionViewSet(ModelViewSet):
    queryset = Introduction.objects.all()
    serializer_class = IntroductionSerializer
``` 

### 2. Implementation of filter function

For filtering the data, let's provide some other attributes as well. The `filter_backends` attribute will determine how your filter will work. You can pass the list of `filter_backends` functions in this attribute. The final `viewset` function with filter will look like following,

```python
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.viewsets import ModelViewSet
from .models import Introduction
from .serializers import IntroductionSerializer

# Introduction viewset function with filter functionality
class IntroductionViewSet(ModelViewSet):
    queryset = Introduction.objects.all()
    serializer_class = IntroductionSerializer
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['id', 'name']
    search_fields = ['=name', 'intro']
    ordering_fields = ['name', 'id']
    ordering = ['id']
```

Here, I have three `filter_backends`,

**1. DjangoFilterBackend:** It will control to filter the fields based on `name` and `id`

The example of filter URL will look like follwoing,
```url
http://localhost:8000/api/introduction/?name=ear
```

**2. SearchFilter:** It will help to search the `name` and `intro` fields. The search behavior may be restricted by prepending various characters to the search_fields,

    1. '^' Starts-with search
    2. '=' Exact matches
    3. '@' Full-text search (Currently only supported Django's PostgreSQL backend)
    4. '$' Regex search

The example of search URL will look like following,
```url
http://localhost:8000/api/introduction/?search=Lorem
```

**3. OrderingFilter:** It will help to order the data based on `name` and `id` fields. By default, the ordering will be according to the `id` field

The example of ordering filter URL will look like following,

```url
http://localhost:8000/api/introduction/?ordering=name
```

Alright, finally you set the filter, search, and ordering functionality in your Django Rest Framework.