How to Pass kwarg to Filter, Getting Error Object

2019-04-17 11:56发布

问题:

In Django Rest Framework want to pass a kwarg to my ClubFilter class from within my view.

class ClubView(ListCreateView):

    queryset = Club.objects.all()
    serializer_class = ClubSerializer

    filter_backends = (DjangoFilterBackend,)
    filter_class = ClubFilter

    def list(self, request, *args, **kwargs):

        queryset = self.filter_queryset(self.get_queryset())

        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

So I tried added self.filter_class = ClubFilter(**kwargs) to the list methoud but I get the error:

'ClubFilter' object is not callable

How can I pass in kwarg to my filter from the view?

回答1:

filter_class must be an class, it can't be class instance. So you must pass that variable when filter object is created.

Creating of filter object is done in filter backend, so you should subclass your filter backend and provide in it some method that can take your kwargs.

Im assuming that you're using DjangoFilterBackend. You can then subclass it like this:

class MyFilterBackend(DjangoFilterBackend):

    def filter_queryset(self, request, queryset, view):
        filter_class = self.get_filter_class(view, queryset)o

        if filter_class:

            if hasattr(view, 'get_filter_kwargs'):
                filter_kwargs = view.get_filter_kwargs(queryset=queryset)
            else:
                filter_kwargs = {'queryset': queryset}

            return filter_class(request.query_params, **filter_kwargs).qs

        return None

That will allow you to create method get_filter_kwargs inside your view, that should return all kwargs that shuld be passed into your filter class. Remember to pass also queryset that is provided in kwarg for that method.



回答2:

You can create custom filter backend

filters.py

class MyFilterBackend(DjangoFilterBackend):
    def filter_queryset(self, request, queryset, view):
        filter_class = self.get_filter_class(view, queryset)

        if filter_class:
            return filter_class(request.query_params, queryset=queryset, **kwargs).qs

    return queryset

and use it instead DjangoFilterBackend