How to cache queryset results in ListAPIView when pagination, filtering, ordering enabled?

How can I cache queryset (and invalidate cache) results in ListAPIView when there is pagination, filtering and ordering possible? Note that I need to invalidate cache per company so if any new Item object is created for a specific company I need to invalidate.

    from rest_framework.generics import ListAPIView
    from rest_framework.pagination import PageNumberPagination

    class CustomPaginationClass(PageNumberPagination):
        page_size = "30"
        page_size_query_param = 'perPage'
        max_page_size = 10000

    class ItemListApiView(ListAPIView):
        model = Item
        authentication_classes = (SessionAuthentication, )
        serializer_class = ItemSerializer
        permission_classes = (HasAccessToItems, )
        pagination_class = CustomPaginationClass
        filter_backends = (filters.SearchFilter, DjangoFilterBackend, filters.OrderingFilter, )
        search_fields = ('user__name', )
        filter_fields = {
            'category_type__name': ['exact'],
            'item_type__name': ['exact'],
            'approver__name': ['exact'],
            'status': ['exact', 'in']
        ordering_fields = '__all__'
        def get_queryset(self):
            qs = Item.objects.filter('company')
            if not self.request.user.is_all_items_enabled:
                qs = qs.filter(approver=self.request.user)
            return qs.order_by('-created')
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)

Do you have an existing, identified problem that you have determined will be resolved by cacheing a queryset? Or is this some theoretical performance improvement that you’re hoping to obtain?

I seriously doubt you’re going to be able to improve upon the query cacheing that PostgreSQL provides.

Keep in mind that in a production environment, you’ll almost definitely have multiple processes running your application and possibly across different systems. Any application-layer cacheing needs to ensure consistency and atomicity across processes.

Also keep in mind that an “unresolved” queryset is just a data structure representing an SQL query - and once it’s evaluated, any re-ordering or filtering results in a new SQL query being generated and evaluated - it does not work on the data previously evaluated. So just cacheing the queryset itself doesn’t provide you with any benefits - you would need to cache the output of the queryset and perform any further processing in your code.

Bottom line? Don’t bother.

1 Like

I totally agree with @KenWhitesell , but if for some scenario you need a performance improvement is better to think in an database index.

1 Like