Created
November 18, 2010 00:15
-
-
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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