Filter a combined queryset in Django Rest Framework

I created a viewset that combines different models that inherit from the same parent model (Transactions). It was working well and I could reach the endpoint. Now I am trying to add filters using django-filters, but I am getting an error:

    model = queryset.model
AttributeError: 'list' object has no attribute 'model'

The fields that I am using to filter and search belong to the parent model.

Here is my viewset:

class TransactionViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = TransactionSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = {
        "company": ["exact"],
    }
    search_fields = ["id", "description"]

    def get_queryset(self):
        payment_collections = PaymentCollection.objects.all()
        up_front_sales = UpFrontSale.objects.all()

        combined_queryset = list(
            chain(
                payment_collections,
                up_front_sales,
            )
        )

        return combined_queryset

I see that the error is that my method returns a list instead of a queryset, but I tried to use the union method instead and got

    raise NotSupportedError(
django.db.utils.NotSupportedError: Calling QuerySet.filter() after union() is not supported.

Is there a way to use the default filterset_fields and search_fields with a combined queryset?

A "smart" hack would be to override the .filter_queryset(..):

class TransactionViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = TransactionSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = {
        "company": ["exact"],
    }
    search_fields = ["id", "description"]

    def filter_queryset(self, queryset):
        payment_collections = super().filter_queryset(PaymentCollection.objects.all())
        up_front_sales = super().filter_queryset(UpFrontSale.objects.all())

        combined_queryset = list(
            chain(
                payment_collections,
                up_front_sales,
            )
        )
        return combined_queryset

But actually the union of two different models is usually something you should try to avoid.

Вернуться на верх