Search code examples
pythondjangodjango-rest-frameworkdjango-viewsdjango-viewsets

How to inherit Generic Filtering in extra action


I want to inherit Generic Filtering include (filterset_fields, search_fields, ordering_fields in extra action sold. So how to do it, and any way better for this case?

class ApartmentViewset(viewsets.ModelViewSet):
    queryset = Apartment.objects.all().order_by('-timestamp')
    serializer_class = ApartmentSerializer
    # Set permission for only user owner apartment can edit it.
    permission_classes = [
        permissions.IsAuthenticatedOrReadOnly, IsOwnerApartmentOrReadOnly]
    # Add search by address, filter by district and ordering by price
    filter_backends = [filters.SearchFilter,
                       DjangoFilterBackend, filters.OrderingFilter]
    filterset_fields = ['district']
    search_fields = ['address', 'seller']
    ordering_fields = (
        'price',
    )

    # fill current username when create new apartment
    def perform_create(self, serializer):
        serializer.save(seller=self.request.user)

    @action(detail=False)
    def sold(self, request):
        queryset = self.queryset.filter(issold=True)
        serialize = self.serializer_class(queryset, many=True)
        return Response(serialize.data)

Solution

  • Generic View (and hence all classes that inherit from it) in DRF has a filter_queryset method which is called by the various mixins to perform filtering, so you can simply call that in your method. If you also want pagination there are the methods paginate_queryset and get_paginated_response:

    class ApartmentViewset(viewsets.ModelViewSet):
        ...
        
        @action(detail=False)
        def sold(self, request):
            queryset = self.filter_queryset(self.queryset.filter(issold=True))
            serialize = self.serializer_class(queryset, many=True)
            return Response(serialize.data)