How do you cache a paginated Django queryset, specifically in a ListView?
I noticed one query was taking a long time to run, so I\'m attempting to cache it. The queryset
The problem turned out to be a combination of factors. Mainly, the result returned by the paginate_queryset()
contains a reference to the unlimited queryset, meaning it's essentially uncachable. When I called cache.set(mykey, (paginator, page, object_list, other_pages))
, it was trying to serialize thousands of records instead of just the page_size
number of records I was expecting, causing the cached item to exceed memcached's limits and fail.
The other factor was the horrible default error reporting in the memcached/python-memcached, which silently hides all errors and turns cache.set() into a nop if anything goes wrong, making it very time-consuming to track down the problem.
I fixed this by essentially rewriting paginate_queryset()
to ditch Django's builtin paginator functionality altogether and calculate the queryset myself with:
object_list = queryset[page_size*(page-1):page_size*(page-1)+page_size]
and then caching that object_list
.