我找到了一个关于缓存模型查询集计数(Blog Post)的精彩教程。它在大多数方面都有效,但在代理模型的情况下会出现奇怪的错误。
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, expires=600):
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]
self.expires = expires
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 = "count_%s" % hashlib.sha224(self._sql).hexdigest()
count = cache.get(key)
if count is None:
count = self._queryset._original_count()
model_name = self._queryset.model._meta.app_label
expiration = self.expires
cache.set(key, count, expiration)
model_cache_list = cache.get(model_name) or []
model_cache_list.append(key)
cache.set(model_name, model_cache_list, expiration)
return count
然后我继续将子类化为Django Queryset类,并按以下方式将上述类添加为方法。
class GenericQuerySet(QuerySet):
def get_cached_count(self, time=None):
cached_count = CachedCountProxy(self, expires=time)
return cached_count()
现在,当我尝试在所有非代理模型查询集上调用get_cached_count时,它会成功。但是,当我在代理模型查询集上调用它时,它会生成以下SQL;
{'time': '0.000', 'sql': u'SELECT COUNT(*) FROM WHERE NOT (`table`.`city_id` IS NULL)'}
请注意FROM子句中缺少表?这太奇怪了,特别是因为同一代理模型上的原始count()方法产生了正确的SQL。在绑定_original_count()方法或将查询集作为整体绑定到_queryset的过程中发生了奇怪的事情。
有什么想法吗?