Search code examples
djangodjango-rest-frameworkdjango-filter

Django_filter on an apiview


I have been trying to use the Django_filter on an APIView, but it just does not work. I am trying to implement a filter search, on some fields on a model.

below is how the model is set up

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=254, unique=True)
    name = models.CharField(max_length=250)
    picture = models.TextField(null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(max_length=255, unique=True, blank=True)

class Skill(models.Model):
    name = models.CharField(max_length=60)
    subcategory = models.CharField(max_length=60, blank=True, null=True)
    created_on = models.DateTimeField(auto_now=True)
    updated_on = models.DateTimeField(auto_now_add=True)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.DO_NOTHING)

the views.py set up is also as shown below

from django_filters import rest_framework as filters


class UserFilter(filters.FilterSet):
    email = filters.CharFilter(lookup_expr='icontains')
    name = filters.CharFilter(lookup_expr='icontains')
    profiles__skills = filters.CharFilter(lookup_expr='icontains')

    class Meta:
        model = User
        fields = ('email', 'name', 'profiles__skills')


class ListUsersView(APIView, MyPaginationMixin):
    '''
    Gets all the users in the database
    '''
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [AllowAny]
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
    filterset_class = UserFilter

    def get(self, request):
        page = self.paginate_queryset(self.queryset)

        if page is not None:
            serializer_context = {"request": request}
            serializer = self.serializer_class(page, context=serializer_context, many=True)
            return self.get_paginated_response(serializer.data)

and finally my serializer.py

class UserSerializer(serializers.ModelSerializer):
    slug = serializers.SlugField(read_only=True)

    class Meta:
        model = User
        fields = ('email', 'name', 'slug', 'picture')
        read_only_fields = ('email', 'name', 'slug',)

my urls.py

path('users/', qv.ListUsersView.as_view(), name='list-users'),

this is how my result looks like enter image description here

please, how can I get the Django filter to work on the APIView


Solution

  • It seems you are trying to get the similar or exact behavior of DRF ListAPIView by using APIView. I would suggest using ListAPIView over APIView in your case.

    from rest_framework import generics
    from django_filters import rest_framework as filters
    
    
    class ListUsersView(generics.ListAPIView):
        '''
        Gets all the users in the database
        '''
        queryset = User.objects.all()
        serializer_class = UserSerializer
        permission_classes = [AllowAny]
        filterset_class = UserFilter
        filter_backends = (filters.backends.DjangoFilterBackend,)

    To add filtering capability in APIView,

    class MyAPIViewKlass(APIView):
        filter_backends = (filters.DjangoFilterBackend,)
    
        def filter_queryset(self, queryset):
            for backend in list(self.filter_backends):
                queryset = backend().filter_queryset(self.request, queryset, self)
            return queryset
    
        def get(self, request, *args, **kwargs):
            base_qs = MyModel.objects.all()
            filtered_qs = self.filter_queryset(base_qs)
            serializer = MySerializer(filtered_qs, many=True)
            return Response(serializer.data)