We will discuss how search can be accomplished in Django REST Framework using query parameter.
Let’s use Django polls models as reference.
Let’s add the following serializer:
Let’s add the following view:
Let’s add the following urlpattern:
A GET request to
/api/polls/questions/ returns a list with all the questions.
DRF provides a filter called
SearchFilter which can filter the queryset based on a query parameter named
We want to search for questions which have
Samsung in the question_text.
This requires adding two attributes on QuestionsAPIView. They are
filter_backends. Let’s add these attributes.
Make a GET request with
search query parameter
The question with term
Samsung in it’s question_text is returned in the response.
Now we want to find questions authored by charles. Let’s make another request having query parameter charles.
We didn’t get the questions authored by charles because we have only
search_fields. DRF is only looking for the search query parameter in
We need to add
search_fields too if we want search query parameter to be looked into
search_fields = ['question_text', 'author']
Make api request again and you should see
charles authored question in response.
Searching on relationship
Question has a many relationship to Choice. Let’s create a Question with an associated Choice.
In : from polls.models import Question, ChoiceIn : q = Question.objects.create(question_text='Who is your favorite GoT character?')In : Choice.objects.create(question=q, choice_text='Ned')
Out: <Choice: Ned>
We want associated choices’ choice_text to be considered too when we search for a particular term. Search for
Ned in questions endpoint.
We didn’t get any result.
Since we want associated choices’ choice_text to be considered we would need to add
search_fields = ['question_text', 'author', 'choice__choice_text']
Ned again and you should see the relevant question in the returned response.
More restrictive search
search_fields back to
Behind the scenes, DRF uses
icontains by default. Search for
DRF essentially applied the following filter:
Q(question_text__icontains='GoT') | Q(author__icontains='GoT')
You might want to enforce that an object should only be returned if it starts with the searched text. In such case, the filtering needed would be
istartswith instead of
SearchFilter has support for
istartswith too. We need to prepend
^ to the field for
search_fields = ['^question_text', 'author']
GoT search wouldn’t return any question in the response now.
Who and you would see the question in response.
DRF under the hood performed the following filter in this case
Q(question_text__istartswith='Who') | Q(author__icontains='Who')
Exact search can be performed by prepending
@ in the attribute name. eg:
Searching on multiple terms
search_fields back to
DRF supports multiple terms in search query parameter. As DRF documentation states:
The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched.
Let’s send two terms
GoT in the search parameter.
Because both the terms are in the question Who is your favorite GoT character?, so this object is returned in the list.
Search for terms
Because both the terms do not appear in any of the questions, so we got an empty list in the response.
My next post talks about implementing dynamic filters in DRF.
Dynamic filters will come in handy in a scenario where the frontend lists all the fields of the model and users can select the fields on which they want the search text to operate upon.
If you liked this post, consider sending 50 claps :)