from django.db import models, IntegrityError, connection, transaction
from django.utils.http import urlquote as django_urlquote
from django.utils.html import strip_tags
+from django.conf import settings as django_settings
from django.core.urlresolvers import reverse
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db.models.signals import post_delete, post_save, pre_save, pre_delete
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
+from django.utils.encoding import force_unicode
from django.contrib.sitemaps import ping_google
import django.dispatch
from forum import settings
def __len__(self):
return len(self.items)
-class ToFetch(str):
+class ToFetch(unicode):
pass
class CachedQuerySet(models.query.QuerySet):
obj.cache()
else:
obj = self.obj_from_datadict(obj)
- obj.reset_original_state()
+
+ obj.reset_original_state()
return obj
to_return = None
to_cache = {}
+ with_aggregates = len(self.query.aggregates) > 0
key_list = self._fetch_from_query_cache(cache_key)
if key_list is None:
- if not len(self.query.aggregates):
+ if not with_aggregates:
values_list = [on_cache_query_attr]
if len(self.query.extra):
to_cache[cache_key] = (datetime.datetime.now(), key_list)
else:
to_return = list(super(CachedQuerySet, self).iterator())
- to_cache[cache_key] = (datetime.datetime.now(), [row.__dict__[on_cache_query_attr] for row in to_return])
+ to_cache[cache_key] = (datetime.datetime.now(), [
+ (row.__dict__[on_cache_query_attr], dict([(k, row.__dict__[k]) for k in self.query.aggregates.keys()]))
+ for row in to_return])
+ elif with_aggregates:
+ tmp = key_list
+ key_list = [k[0] for k in tmp]
+ with_aggregates = [k[1] for k in tmp]
+ del tmp
if (not to_return) and key_list:
row_keys = [self.model.infer_cache_key({on_cache_query_attr: attr}) for attr in key_list]
cached = cache.get_many(row_keys)
to_return = [
- (ck in cached) and self.obj_from_datadict(cached[ck]) or ToFetch(key_list[i]) for i, ck in enumerate(row_keys)
+ (ck in cached) and self.obj_from_datadict(cached[ck]) or ToFetch(force_unicode(key_list[i])) for i, ck in enumerate(row_keys)
]
if len(cached) != len(row_keys):
- to_fetch = [str(tr) for tr in to_return if isinstance(tr, ToFetch)]
+ to_fetch = [unicode(tr) for tr in to_return if isinstance(tr, ToFetch)]
- fetched = dict([(str(r.__dict__[on_cache_query_attr]), r) for r in
+ fetched = dict([(force_unicode(r.__dict__[on_cache_query_attr]), r) for r in
models.query.QuerySet(self.model).filter(**{"%s__in" % on_cache_query_attr: to_fetch})])
- to_return = [(isinstance(tr, ToFetch) and fetched[str(tr)] or tr) for tr in to_return]
+ to_return = [(isinstance(tr, ToFetch) and fetched[unicode(tr)] or tr) for tr in to_return]
to_cache.update(dict([(self.model.infer_cache_key({on_cache_query_attr: attr}), r._as_dict()) for attr, r in fetched.items()]))
+ if with_aggregates:
+ for i, r in enumerate(to_return):
+ r.__dict__.update(with_aggregates[i])
+
if len(to_cache):
cache.set_many(to_cache, 60 * 60)
if to_return:
for row in to_return:
if hasattr(row, 'leaf'):
- yield row.leaf
- else:
- yield row
+ row = row.leaf
- def _get_query_hash(self):
- return md5(unicode(self.query).encode("utf-8")).hexdigest()
+ row.reset_original_state()
+ yield row
+ def _get_query_hash(self):
+ try:
+ return md5(unicode(self.query).encode("utf-8")).hexdigest()
+ except:
+ try:
+ return md5(self.query).hexdigest()
+ except:
+ return md5(str(self.query)).hexdigest()
class CachedManager(models.Manager):
use_for_related_fields = True
- def get_query_set(self):
+ def get_queryset(self):
return CachedQuerySet(self.model)
def get_or_create(self, *args, **kwargs):
cls.add_to_class("reset_%s_cache" % name, reset_cache)
-class BaseMetaClass(models.Model.__metaclass__):
+class BaseMetaClass(type(models.Model)):
to_denormalize = []
def __new__(cls, *args, **kwargs):
pk = [v for (k,v) in querydict.items() if k in ('pk', 'pk__exact', 'id', 'id__exact'
) or k.endswith('_ptr__pk') or k.endswith('_ptr__id')][0]
- return cls._generate_cache_key(pk)
+ cache_key = cls._generate_cache_key(pk)
+
+ if len(cache_key) > django_settings.CACHE_MAX_KEY_LENGTH:
+ cache_key = cache_key[:django_settings.CACHE_MAX_KEY_LENGTH]
+
+ return cache_key
except:
return None