Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply a filter backend to all fields of all resources in Django Rest Framework?

I have a lot of resources and i want to apply the DjangoFilterBackend to all of them.

Tried setting in settings.py

'DEFAULT_FILTER_BACKENDS': [
            'rest_framework.filters.DjangoFilterBackend',
        ]

But it didn't work

I tried adding only filter_backends = (filters.DjangoFilterBackend,) to one of my resources and it still didn't work.

Only after I explicitly added filter_fields = ('col1','col2',) it started working with those fields only.

Is there any way I can apply the filter backend to all resources and all fields (same way i do with permissions for example ... ) ?

Thanks.

like image 834
haki Avatar asked Nov 30 '14 16:11

haki


People also ask

How do I filter Queryset in Django REST framework?

The simplest way to filter the queryset of any view that subclasses GenericAPIView is to override the .get_queryset() method. Overriding this method allows you to customize the queryset returned by the view in a number of different ways.

What is filter backend in Django?

The DjangoFilterBackend class is used to filter the queryset based on a specified set of fields. This backend class automatically creates a FilterSet (django_filters. rest_framework. FilterSet) class for the given fields. We can also create our own FilterSet class with customized settings.


1 Answers

Right now you are telling Django REST Framework to use the DjangoFilterBackend for all views, but you are not telling it how the FilterSet should be generated.


django-filter will automatically generate a FilterSet for all of the fields on a model if the fields are set to None. Django REST Framework will automatically generate a FilterSet if filter_fields are not set to None, which means you won't be able to use the default DjangoFilterBackend.

You can create a custom DjangoFilterBackend though, which will automatically generate the FilterSet for all fields on the model.

from rest_framework.filters import DjangoFilterBackend

class AllDjangoFilterBackend(DjangoFilterBackend):
    """
    A filter backend that uses django-filter.
    """

    def get_filter_class(self, view, queryset=None):
        """
        Return the django-filters `FilterSet` used to filter the queryset.
        """
        filter_class = getattr(view, 'filter_class', None)
        filter_fields = getattr(view, 'filter_fields', None)

        if filter_class or filter_fields:
            return super(AllDjangoFilterBackend, self).get_filter_class(self, view, queryset)

        class AutoFilterSet(self.default_filter_set):
            class Meta:
                model = queryset.model
                fields = None

        return AutoFilterSet

This will still use the original filter backend for situations where the view defines a custom filter_class or filter_fields, but it will generate a custom FilterSet for all other situations. Keep in mind that you shouldn't allow fields which aren't returned through the API to be filtered, as you are opening yourself up to future security issues (like people filtering a user list by passwords).

like image 125
Kevin Brown-Silva Avatar answered Sep 28 '22 09:09

Kevin Brown-Silva