Filtering
Overview
Filtering allows you to specify certain criteria for selecting objects from the database and returning them in the API response. This can be done using query parameters in the URL, which are used to construct a query to filter the objects.
Introduction to Filtering
The Django filtering feature allows you to retrieve specific objects from the database based on certain conditions. This is done by including certain parameters in the API endpoint's URL. For example, in an API endpoint for a list of items, you could use a filter to only retrieve items that belong to a specific category by adding the category as a query parameter in the URL. DRF has various filtering tools that can be used to filter the queryset of your views, one of them being the DjangoFilterBackend which uses Django's ORM filter method for filtering.
Filtering Against the Current User
In Django, you can filter a queryset against the current user by using the user attribute of the request object. You can filter the queryset to limit the results to those that are relevant to the authenticated user by adding a condition to the query, such as queryset = queryset.filter(user=request.user).
Note that the user attribute of the request object is an instance of the User model (or a subclass), representing the currently authenticated user. If the user is not authenticated, the user attribute will be None.
And remember if you want to filter based on the currently logged-in user, you need to make sure that you are allowing the user to be authenticated.
Filtering Against the URL
Another approach to filtering data in a queryset is to use information present in the URL to restrict the results. This method can be implemented by capturing specific parts of the URL using regular expressions and using that information in the view to filter the queryset before returning the data to the client.
You could then create a view that returned a client queryset filtered by the URL's username:
Filtering Against Query Parameters
Determining the first queryset depends on query parameters in the URL is an example of filtering the first queryset.
Generic Filtering
Generic filtering refers to the ability to filter the results of a list view by using query parameters in the URL. Django REST framework (DRF) provides several generic filter backends that you can use to filter the results of a list view, such as SearchFilter and OrderingFilter. These filter backends can be used together with the Django-filter package to easily add filtering capabilities to your views.
Setting Filter Backends
In the Django REST framework (DRF), you can set the filter backends for a view by specifying the filter_backends attribute on the view class. But for using this filter you have to add the filter in your settings.py file
Here is an example of how you can set filter backends for a view:
In this example, MyViewSet uses SearchFilter, OrderingFilter, and DjangoFilterBackend as filter backends.
Filtering and Object Lookups
When a filter backend is configured for a view, it will be used to automatically filter the data that is returned to the client when that view is accessed. This includes both when the view is used to display a list of objects, as well as when it is used to display a single object.
For example, in a view that is set up to display a list of products, a filter backend could be used to filter the products based on certain criteria such as price range or category. If that same view is also set up to display a single product when a specific product ID is provided in the URL, the filter backend will be applied to the queryset used to retrieve that single product as well.
Overriding the Initial queryset
The initial queryset for a view can be overridden by defining a get_queryset() method on the view. This method should return the desired queryset, which will then be used for the view's primary data source. You can use both an overridden get_queryset() along with generic filtering together, and everything will work as expected. For example, a view that displays a list of all products in a store using a ModelViewSet could have the following get_queryset() method:
API Guide
DjangoFilterBackend
The django-filter library provides a DjangoFilterBackend class which can be used to add customizable filtering options to views that use the Django REST framework. To use DjangoFilterBackend, first, install django-filter.
Once you installed django-filter add 'django_filters' to Django's INSTALLED_APPS:
To use DjangoFilterBackend, you need to add it to the DEFAULT_FILTER_BACKENDS setting in your Django project's settings file:
If you only need to implement simple filtering based on equality, you can set the filterset_fields attribute on a view or viewset, instead of creating a separate filter class. This will automatically generate a filter class for you with filters for each field specified in the filterset_fields attribute.
For example, if you want to allow filtering the ProductViewSet on the name and category fields:
This will automatically generate a filter class which will filter the queryset based on the name and category fields in the request. For example, a client can filter the products by including query parameters in the request like /products?name=example&category=test
SearchFilter
The SearchFilter class provided by the Django REST framework allows for simple searching of a queryset based on a single query parameter. It is based on the search functionality of the Django admin and allows for a quick implementation of search functionality in an API. To use the SearchFilter class, you need to add it to the DEFAULT_FILTER_BACKENDS setting in your Django project's settings file:
Once the SearchFilter class is added to the DEFAULT_FILTER_BACKENDS, it will automatically be applied to all views that use the Django REST framework's ListAPIView or ListCreateAPIView.
You also can add it directly on your viewset or ListAPIView
By default, the SearchFilter class will search against all fields specified in the search_fields attribute of the view. In this example, the queryset will be filtered based on the name, category, and description fields. If a client sends a request like /products?search=example, the SearchFilter class will filter the queryset based on the name, category and description fields and return the products that contain "example" in the fields.
OrderingFilter
The OrderingFilter class provided by the Django REST framework allows for simple ordering of a queryset based on query parameters. This allows clients to request specific ordering of the results, rather than always returning the results in the same order. To use the OrderingFilter class, you need to add it to the DEFAULT_FILTER_BACKENDS setting in your Django project's settings file:
Once the OrderingFilter class is added to the DEFAULT_FILTER_BACKENDS, it will automatically be applied to all views that use the Django REST framework's ListAPIView or ListCreateAPIView.
You also can add it directly on your viewset or ListAPIView
By default, the OrderingFilter class will order the results based on the fields specified in the ordering_fields attribute of the view. In this example, the queryset will be ordered based on the name and price fields. If a client sends a request like /products?ordering=name, the OrderingFilter class will order the queryset by the name field in ascending order. You can also specify the order by using a - in front of the field /products?ordering=-name to order descending.
By default, the ordering parameter is not required and if not provided, the queryset will not be ordered. You can also set the ordering attribute on the view to a string which will be the default ordering for the queryset. The ordering attribute may be either a string or a list/tuple of strings.
Custom Generic Filtering
In Django, you can create your custom generic filtering by creating a custom filter class and then using it in your views or viewsets. A custom filter class should inherit from django_filters.FilterSet and define the filters you want to use.
Example
You can create a custom filter class ProductFilter for filtering products based on name, category, and price:
You can then use this custom filter class in your views or viewsets:
Customizing the Interface
To present an interface for a custom filter in the browsable API, you can implement the to_html() method on your custom filter class. The to_html() method should return a rendered HTML representation of the filter. The to_html() method should have the following pattern:
This method takes in the request, queryset, and the view as arguments, which can be used to generate the HTML representation of the filter.
Filtering & Schemas
In addition to providing an interface for the filter in the browsable API, you can also make the filter controls available to the schema autogeneration that the Django REST framework (DRF) provides. To do this, you can implement the get_schema_fields() method on your custom filter class. The get_schema_fields() method should have the following signature:
This method takes in the view as an argument, which can be used to generate the list of coreapi.Field instances.
Third-Party Packages
There are several third-party packages available that provide additional filter implementations for the Django REST framework (DRF). Here are a few examples:
Django REST Framework Filters Package
Django REST framework (DRF) filters are a package that allows for easy filtering of querysets in a Django REST framework view. It is built on top of the django-filter package, which provides a FilterSet class that can be used to filter querysets based on URL parameters. To use the filters package in your project, you will need to add it to your INSTALLED_APPS setting, and add it to the DEFAULT_FILTER_BACKENDS setting in the REST_FRAMEWORK setting in your project's settings file:
Django REST Framework Full Word Search Filter
Django REST framework (DRF) provides a built-in SearchFilter that allows for simple search functionality based on a single query parameter. By default, it uses the __icontains lookup to perform a case-insensitive search on all fields of the model. But if you need to perform a full word search with DRF, you can create your custom filter class. One way to do this is to use the django.db.models.Q object to combine multiple __iexact lookups to ensure that only exact matches are returned.
Django URL Filter
The django-url-filter package provides a way to filter data via human-friendly URLs. It works by using a similar approach to Django REST framework (DRF) serializers and fields, where you can define filter sets and filters, and they can be nested. This allows for easy filtering of related data. The FilterSet class is similar to the FilterSet class in the django-filter package, but it's more flexible since it can be used to filter other sources of data, not only Django querysets. django-url-filter also provides a FilterSet class that can be used to filter other sources of data such as Python lists or dictionaries. This package is quite flexible, easy to use, and can be used for filtering other sources of data, not only Django querysets, and also can be used in conjunction with the DRF views, viewsets, and even in django views
drf-URL-filters
drf-url-filter is a simple Django app that allows you to apply filters on the queryset of a Django REST framework (DRF) ModelViewSet in a clean, simple, and configurable way. It also supports validations on the incoming query parameters and their values. The package uses the Voluptuous library to handle the validations on the incoming query parameters. Voluptuous is a Python package that provides a powerful and easy-to-use validation library. It allows you to define your validations for the query parameters, which gives you a lot of flexibility in how you handle the incoming data.
Conclusion
- Filtering allows you to specify certain criteria for selecting objects from the database and returning them in the API response.
- Django filtering feature allows you to retrieve specific objects from the database based on certain conditions.
- Django REST framework (DRF) provides several generic filter backends that you can use to filter the results of a list view, such as SearchFilter and OrderingFilter.
- When a filter backend is configured for a view, it will be used to automatically filter the data that is returned to the client when that view is accessed.
- The initial queryset for a view can be overridden by defining a get_queryset() method on the view.
- The SearchFilter class provided by the Django REST framework allows for simple searching of a queryset based on a single query parameter.
- In Django, you can create your custom generic filtering by creating a custom filter class and then using it in your views or viewsets.