Skip to content

Instantly share code, notes, and snippets.

@timtrueman
Created November 18, 2010 00:15
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save timtrueman/704412 to your computer and use it in GitHub Desktop.
Save timtrueman/704412 to your computer and use it in GitHub Desktop.
Django cached .count() proxy for querysets that is generic and works with pagination in object_list (which clones and overrides any monkeypatched count method so you have to override the clone method first).
class CachedCountCloneProxy(object):
''' This allows us to monkey-patch count() on QuerySets so we can cache it and speed things up.
._clone is called so we have to monkey-patch that first...
'''
def __init__(self, queryset):
self._queryset = queryset
self._queryset._clone_original = self._queryset._clone
def __call__(self):
queryset = self._queryset._clone_original()
queryset.count = CachedCountProxy(queryset)
return queryset
class CachedCountProxy(object):
''' This allows us to monkey-patch count() on QuerySets so we can cache it and speed things up.
'''
def __init__(self, queryset):
self._queryset = queryset
self._queryset._original_count = self._queryset.count
self._sql = self._queryset.query.get_compiler(self._queryset.db).as_sql()
self._sql = self._sql[0] % self._sql[1]
def __call__(self):
''' 1. Check cache
2. Return cache if it's set
3. If it's not set, call super and get the count
4. Cache that for X minutes
'''
key = "paginator_count_%s" % hashlib.sha224(self._sql).hexdigest()
count = cache.get(key)
if count is None:
count = self._queryset._original_count()
cache.set(key, count, 300)
return count
# To use:
# queryset._clone = CachedCountCloneProxy(queryset) # monkeypatch solution to cache the count for performance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment