Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use normal Filter together with SearchFilter on Django Rest Framework?

I'm using DRF(Django Rest Framework).

I declared a ModelViewSet, and now I want to add filters on that.

class GoodsViewSet(viewsets.ModelViewSet):
    class Filter(FilterSet):    
        class Meta:
            model = m.Goods

    filter_class = Filter
    filter_backends = (SearchFilter, Filter)
    search_fields = ['name',]
    queryset = m.Goods.objects.all()
    serializer_class = s.GoodsSerializer

Seeing that I declared a Filter sub class and applied it with:

filter_class = Filter

It worked at the beginning, before I add the lines:

filter_backends = (SearchFilter, Filter)
search_fields = ['name',]

Which was told by the doc.

And now the search filter is applied while the normal filter_class is skipped.

One word, they cannot work together.

How to work around this?

like image 230
Alfred Huang Avatar asked Nov 04 '16 08:11

Alfred Huang


People also ask

Can we use Django and Django REST framework together?

Django Rest Framework makes it easy to use your Django Server as an REST API. REST stands for "representational state transfer" and API stands for application programming interface. Note that with DRF you easily have list and create views as well as authentication.

What is the purpose of filter () method in Django?

The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.

How do you implement a search in DRF?

DRF is only looking for the search query parameter in question_text . We need to add author to search_fields too if we want search query parameter to be looked into author . Modify search_fields . Make api request again and you should see charles authored question in response.


2 Answers

Finally, I found we should specify two filter_backends together:

from rest_framework.filters import SearchFilter
from django_filters.rest_framework import DjangoFilterBackend

class GoodsViewSet(viewsets.ModelViewSet):
    class Filter(FilterSet):    
        class Meta:
            model = m.Goods

    filter_class = Filter
    filter_backends = (SearchFilter, DjangoFilterBackend)
    search_fields = ['name',]
    queryset = m.Goods.objects.all()
    serializer_class = s.GoodsSerializer

Or we can ignore the filter_backends field on a specific ViewSet class, but apply them globally in settings.py:

REST_FRAMEWORK = {
    # ... other configurations
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.filters.SearchFilter',
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
}

So that the filter_class and search_fields options are available on the ViewSet at the same time.

like image 80
Alfred Huang Avatar answered Oct 16 '22 14:10

Alfred Huang


this worked for me:

    from django_filters import rest_framework as filters
    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework.filters import SearchFilter, OrderingFilter

--------views.py-----------------------------

    filter_backends = (filters.DjangoFilterBackend, SearchFilter ,OrderingFilter)
    filter_fields =('completed',)
    ordering =('-date_created',)
    search_fields =('task_name',)
like image 27
ABHAY KOTAL Avatar answered Oct 16 '22 14:10

ABHAY KOTAL