Introduction to Advanced Filtering

Welcome back! In this lesson, we'll dive into advanced filtering techniques to make our To-Do API even more powerful and user-friendly. You've already learned the basics of filtering in the previous lesson. Here, we will focus on adding more flexible filtering capabilities using the django-filter library, which makes complex queries easier to handle. By the end of this lesson, you will be able to create custom filters to refine your API queries.

Recap of Initial Setup

Before we get started with advanced filtering, let's briefly recap the initial setup of our Django-based To-Do API. This will ensure we're all on the same page.

Here's the summary code of our current setup:

# project/myapp/models.py
from django.db import models

class Todo(models.Model):
    task = models.CharField(max_length=255)
    completed = models.BooleanField(default=False)
    priority = models.IntegerField()
    assignee = models.CharField(max_length=255, blank=True, null=True)
    group = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return self.task
    
# project/myapp/serializers.py
from rest_framework import serializers
from .models import Todo

class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = '__all__'

This setup provides a model we will work with. Now, let's take it a step further by adding powerful filtering options.

Creating Custom Filters

The django-filter library allows you to create advanced custom filters. Filters are defined in a FilterSet class that specifies which fields are available for filtering and how filtering should be performed. We will create a separate filters.py file to store filters. Inside, we'll define a TodoFilter class to filter To-Do items based on various fields. This class should be inherited from filters.FilterSet, as follows:

# project/myapp/filters.py
from django_filters import rest_framework as filters
from .models import Todo

class TodoFilter(filters.FilterSet):
    pass
Advanced Filter: Strings

A common filter is one that allows you to search for a field containing specific text. For example, to filter tasks based on a substring match in their names, use the CharFilter with lookup_expr set to icontains:

task = filters.CharFilter(lookup_expr='icontains')

Here, we create a filter for the task field, allowing case-insensitive, partial matches using icontains. This means users can find To-Do items with tasks that include specific text. However, it's important to note that the behavior of icontains and contains can depend on your database settings, particularly the collation settings. Some databases may not support case-insensitive searches by default, which could affect the functionality of icontains.

For other cases, django-filters provide a comprehensive set of options for lookup_expr:

  • exact: Matches exactly.
  • iexact: Case-insensitive exact match.
  • contains: Contains substring.
  • icontains: Case-insensitive contains substring.
  • startswith: Starts with substring.
  • istartswith: Case-insensitive starts with substring.
  • endswith: Ends with substring.
  • iendswith: Case-insensitive ends with substring.
Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal