Customizing Filters in Django REST Framework - GeeksforGeeks

05 Jul, 2021
Prerequisite: Adding Filtering in APIs – Django REST Framework [lin needed article on published yet]
Django filters facilitate filtering the queryset to retrieve the relevant results based on the values assigned to the filter fields. But, what if the user wants to retrieve details within a given range. Say, for example, the user needs to fetch detail of robots based on price range. Here comes the necessity of customizing the filters. Let’s create and apply a customized filter to the Robot model so that the user can retrieve robot details by providing robot category name, manufacturer name, currency, manufacturing date range, and/or price range.  
We will create a new class named RobotFilter class, which is a subclass of django_filters.FilterSet class.  Let’s declare the imports
Python3
from django_filters import FilterSet, AllValuesFilterfrom django_filters import DateTimeFilter, NumberFilter
Now, you can add the below code before the RobotList class.
Python3
class RobotFilter(FilterSet):    from_manufacturing_date = DateTimeFilter(field_name='manufacturing_date',                                             lookup_expr='gte')    to_manufacturing_date = DateTimeFilter(field_name='manufacturing_date',                                           lookup_expr='lte')    min_price = NumberFilter(field_name='price', lookup_expr='gte')    max_price = NumberFilter(field_name='price', lookup_expr='lte')    robotcategory_name = AllValuesFilter(field_name='robot_category__name')    manufacturer_name = AllValuesFilter(field_name='manufacturer__name')      class Meta:        model = Robot        fields = (            'name',            'currency',            'from_manufacturing_date',            'to_manufacturing_date',            'min_price',            'max_price',            'robotcategory_name',            'manufacturer_name',            )
Let’s look at the attributes declared in the RobotFilter class.
from_manufacturing_date
to_manufacturing_date
min_price
max_price
robotcategory_name
manufacturer_name
from_manufacturing_date: It is a django_filters.DateTimeFilter instance attribute that filters the robots whose manufacturing_date value is greater than or equal to the specified DateTime value. Here in the DateTimeFilter, there are two parameters named field_name and lookup_expr. The field_name has the manufacturing_date (for filtering), and ‘gte’ (greater than or equal to) is applied to the lookup_expr.
to_manufacturing_date: It is a django_filters.DateTimeFilter instance attribute that filters the robots whose manufacturing_date value is less than or equal to the specified DateTime value. Here in the DateTimeFilter, there are two parameters named field_name and lookup_expr. In the field_name, we mentioned the manufacturing_date, and ‘lte’ (less than or equal to) is applied to the lookup_expr.
min_price: It is a django_filters.NumberFilter instance attribute that filters the robots whose price value is greater than or equal to the specified price value.
max_price: It is a django_filters.NumberFilter instance attribute that filters the robots whose price value is less than or equal to the specified price value.
robotcategory_name: It is a django_filters.AllValuesFilter instance attribute that filters the robots whose robot category name matches with the specified string value. You can notice that there is a double underscore (__) in the value provided to the field_name, between robot_category and name. The field_name uses the Django double underscore to read it as the name field for the RobotCategory model. This helps to retrieve the robot’s detail based on the robot category name rather than its pk id.
manufacturer_name: It is a django_filters.AllValuesFilter instance attribute that filters the robots whose manufacturer name matches with the specified string value. The field_name uses the Django double underscore to read the value ‘manufacturer__name’ as the name field for the Manufacturer model. This helps to retrieve the robot’s detail based on the manufacturer name rather than its pk id.
The RobotFilter class also defines a Meta inner class. This class has two attributes model and fields. The model attribute specifies the model (Robot) to filter. And, the fields attribute holds field names and filter names (as a tuple of strings) to include in the filters for the mentioned model (Robot). 
Let’s use the RobotFilter class in our RobotList class. The code as follows
Python3
class RobotList(generics.ListCreateAPIView):    queryset = Robot.objects.all()    serializer_class = RobotSerializer    name = 'robot-list'    # customized filter class    filter_class = RobotFilter    search_fields = (        '^name',    )    ordering_fields = (        'price',    )
Let’s filter the robots within a manufacturing date. The HTTPie command is
http “:8000/robot/?from_manufacturing_date=2019-10-01&to_manufacturing_date=2020-03-01”
Output:
Let’s filter the robots based on the robot category name and manufacturer name. The HTTPie command as follows
http “:8000/robot/?robotcategory_name=Articulated Robots&manufacturer_name=Fanuc”
Output:
Let’s filter the robots based on price range. The HTTPie command is
http “:8000/robot/?min_price=10000&max_price=20000¤cy=USD”
Output:
Let’s filter the robots using the browsable API feature. You can browse the below URL and click the filter button.
http://127.0.0.1:8000/robot/
You can populate the values to filter against robots. Sharing the screenshot below
On clicking the submit button, you will get filtered results. Sharing the screenshot below
Django-REST
Python Django
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
How to Install PIP on Windows ?
How to drop one or multiple columns in Pandas Dataframe
Python OOPs Concepts
Python | Get unique values from a list
Check if element exists in list in Python
Python Classes and Objects
Python | os.path.join() method
How To Convert Python Dictionary To JSON?
Python | Pandas dataframe.groupby()
Create a directory in Python