最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Filter a combined queryset in Django Rest Framework - Stack Overflow

programmeradmin4浏览0评论

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?

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?

Share Improve this question asked Feb 17 at 0:11 Oskar Adolfo Villa LópezOskar Adolfo Villa López 131 silver badge3 bronze badges New contributor Oskar Adolfo Villa López is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
Add a comment  | 

1 Answer 1

Reset to default 1

A "smart" hack would be to override the .filter_queryset(…) [drf-doc]:

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

    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.

发布评论

评论列表(0)

  1. 暂无评论