Open In App

Filter data in Django Rest Framework

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Django REST Framework’s generic list view, by default, returns the entire query sets for a model manager. For real-world applications, it is necessary to filter the queryset to retrieve the relevant results based on the need.  So, let’s discuss how to create a RESTful Web Service that provides filtering capabilities. 

  • DjangoFilterBackend
  • SearchFilter
  • OrderingFilter

Note: You can refer The Browsable API section for Models, Serializers, and Views of Project used in the article

DjangoFilterBackend

The DjangoFilterBackend class is used to filter the queryset based on a specified set of fields. This backend class automatically creates a FilterSet (django_filters.rest_framework.FilterSet) class for the given fields. We can also create our own FilterSet class with customized settings.

To configure filter backend classes in our Django Web Service, we need to install the django-filter package in our virtual environment. Make sure you quit the Django development server (Ctrl + C) and activate the virtual environment. Let’s run the below command.

pip install django-filter

After installation, we need to define the django_filters application to INSTALLED_APPS in the settings.py file.

Python3




INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Django REST framework
    'rest_framework',
    'robots.apps.RobotsConfig',
    # Django Filters
    'django_filters',
]


As a next step, we need to set the DjangoFilterBackend class from django_filters as the default filter class. Let’s mention it to the REST_FRAMEWORK dictionary in the settings.py file. 

Python3




REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS'🙁
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
}


Now our RESTful web service is configured to make use of the filtering feature provided by django_filters.rest_framework.DjangoFilterBackend class. Let’s filter the robot class that retrieves a list of robots. The RobotList class as follows:

Python3




class RobotList(generics.ListCreateAPIView):
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
      
    filter_fields = (
        'robot_category',
        'manufacturer',
    )


Here, you can notice an attribute named filter_fileds where we specify the field name to filter against. Now, we can retrieve robots based on their category (robot_category) and/or manufacturer. 

Let’s filter the robots based on the robot category. The HTTPie command is

http “:8000/robot/?robot_category=2”

Output:

Let’s try another HTTPie command that filters robots based on robot category and manufacturer. The HTTPie command is

http “:8000/robot/?robot_category=2&manufacturer=1”

Output:

Now let’s check the functionality in Browsable API. You can browse the below URL

http://127.0.0.1:8000/robot/

You can click the Filters button in the top right corner to make use of the filter feature. It will display as shown below

On clicking the submit button you will get the result based on the populated filter fields as shown below.

SearchFilter

The SearchFilter class supports a single query parameter-based searching feature, and it is based on the Django admin’s search function.

By default, SearchFilter class uses case-insensitive partial matches, and it may contain multiple search terms (should be whitespace and/or comma-separated). We can also restrict the search behavior by prepending various characters to the search_fields. 

  • ‘^’ Starts-with search.
  • ‘=’ Exact matches.
  • ‘@’ Full-text search. ( for Django’s PostgreSQL backend)
  • ‘$’ Regex search

By default, the search parameter is named search, and you can override it with the SEARCH_PARAM setting. Let’s make use of SearchFilter class by adding the rest_framework.filters.SearchFilter class to the REST_FRAMEWORK dictionary. 

Python3




REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS'🙁
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
    ),
}


Our RobotList class looks as follows:

Python3




class RobotList(generics.ListCreateAPIView):
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
      
    search_fields = (
        '^name',
    )


The search_fields attribute specifies a tuple of strings, which indicates the field names that we want to include in the search feature. 

Let’s search the robots, which starts with the name ‘IRB’. The HTTPie command is

http “:8000/robot/?search=IRB”

Output:

OrderingFilter

The OrderingFilter class allows you to order the result based on the specified fields. By default, the query parameter is named ordering, and it can be overridden with the ORDERING_PARAM setting. The ordering_field attribute specifies a tuple of strings, which indicates the field names to sort the results.

If you don’t specify an ordering_fields attribute on the view, the filter class allows the user to filter on any readable fields specified by the serializer_class attribute. This permits the user to order against sensitive information such as password hash fields and so on, which may lead to unexpected data leakage. You can also specify a default order by setting an ordering attribute on the view. It can be either a string or a list/tuple of strings.

To make use of  OrderingFilter class, we need to set the class as the default ordering filter class to the REST_FRAMEWORK dictionary.

Python3




REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS'🙁
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.OrderingFilter',
    ),
}


Let’s mention the ordering_fields attribute on the RobotList class. The code as follows:

Python3




class RobotList(generics.ListCreateAPIView):
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    name = 'robot-list'
  
    ordering_fields = (
        'price',
    )


Now, let’s retrieve robots based on the increase in price order. The HTTPie command is

http “:8000/robot/?ordering=price”

Output:



Last Updated : 30 May, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads