Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using filters with list_routes in drf

Is there a way to use filters for @list_route the same way you use them for the root ViewSet in DRF?

I have a model that I have configured filters for and a detail route that I cannot:

class ListingViewSet(viewsets.ModelViewSet):
    # disable listing after 5 flags
    queryset = Listing.objects.all()

    serializer_class = ListingSerializer
    filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter)
    permission_classes = (ListingOwnerCanEdit,)
    filter_class = ListingFilter

    @list_route()
    def homepage(self, request):
        queryset = Listing.objects.filter(flags__lt=5, closed=False)

        ### Doesn't work
        # filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter)
        # permission_classes = (ListingOwnerCanEdit,)
        # filter_class = ListingFilter
        # ordering_filter = OrderingFilter()
        # ordering_fields = ('price', 'views')
        # search_fields = ('title', 'description')

        serializer = ListingSerializer(queryset, many=True, context=self.get_serializer_context())
        return Response(serializer.data)

And ListingFilter is:

class ListingFilter(django_filters.rest_framework.FilterSet):
    min_price = django_filters.NumberFilter(name="price", lookup_expr='gte')
    max_price = django_filters.NumberFilter(name="price", lookup_expr='lte')
    author_pk = django_filters.CharFilter(name='author_pk')

    class Meta:
        model = Listing
        fields = ['price_type', 'sale_type', 'category__name', 'min_price', 'max_price', 'description', 'title',
              'listing_date', 'views', 'number_of_inquiries', 'author_pk', 'closed', 'closing_date']

Is there a way to use ListingFilter with the homepage list route?

like image 568
Juan Torres Avatar asked Mar 08 '17 21:03

Juan Torres


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.

Why are filters used in Django framework?

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

What is filter backend?

Filtering backend allow you to achieve various filtering (search, ordering etc.) with writing just a line of code (that is enabling the filter backend). You could achieve the same result by not using any filter backend and instead filtering yourself using the query parameter.


1 Answers

You should call filter_queryset in your method decorated with @list_route:

@list_route()
def homepage(self, request):
    queryset = self.get_queryset().filter(flags__lt=5, closed=False)
    queryset = self.filter_queryset(queryset)

    serializer = ListingSerializer(queryset, many=True, context=self.get_serializer_context())
    return Response(serializer.data)

Edit: it is also a good idea to use self.get_queryset() instead of Listing.objects.

like image 199
pchiquet Avatar answered Sep 18 '22 08:09

pchiquet