X-Git-Url: https://git.openstreetmap.org./osqa.git/blobdiff_plain/50d5fd554fe0f2633459ba3e8e57674869ba1643..183aa1f98a61acb441e082951ff8c24c93cfcc27:/forum/models/base.py diff --git a/forum/models/base.py b/forum/models/base.py index 1111b43..9c328c5 100644 --- a/forum/models/base.py +++ b/forum/models/base.py @@ -8,6 +8,7 @@ from urllib import quote_plus, urlencode 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 @@ -16,6 +17,7 @@ from django.template.defaultfilters import slugify 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 @@ -41,7 +43,7 @@ class LazyQueryList(object): def __len__(self): return len(self.items) -class ToFetch(str): +class ToFetch(unicode): pass class CachedQuerySet(models.query.QuerySet): @@ -81,7 +83,8 @@ class CachedQuerySet(models.query.QuerySet): obj.cache() else: obj = self.obj_from_datadict(obj) - obj.reset_original_state() + + obj.reset_original_state() return obj @@ -118,10 +121,11 @@ class CachedQuerySet(models.query.QuerySet): 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): @@ -131,25 +135,36 @@ class CachedQuerySet(models.query.QuerySet): 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) @@ -157,19 +172,25 @@ class CachedQuerySet(models.query.QuerySet): 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): @@ -205,7 +226,7 @@ class DenormalizedField(object): 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): @@ -310,7 +331,12 @@ class BaseModel(models.Model): 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