def fetch_by_id(self): if self.cache_fetch_by_id_queryset and self.cache_queryset_enable: vals = self.values_list('pk', *self.query.extra.keys()) else: vals = self.no_cache().values_list('pk', *self.query.extra.keys()) ids = [val[0] for val in vals] if self.cache_object_enable: keys = dict((get_cache_key_for_pk(self.model, i), i) for i in ids) cached = dict((k, v) for k, v in cache.get_many(keys).items() if v is not None) missed = [pk for key, pk in keys.iteritems() if key not in cached] new = {} if missed: objects = self.model._default_manager.filter(pk__in=missed) new = dict((get_cache_key_for_pk(self.model, o.pk), o) \ for o in objects) cache.set_many(new) objects = dict((o.pk, o) for o in cached.values() + new.values()) for pk in ids: yield objects[pk] else: qs = self.model._orm_manager.no_cache().filter(pk__in=ids) if connection.vendor == 'postgresql': with server_side_cursors(qs, itersize=10): for obj in qs.iterator(): yield obj else: for obj in qs.iterator(): yield obj
def ensure_default_manager(sender, **kwargs): from django_orm.cache.utils import get_cache_key_for_pk from django_orm.cache.invalidator import invalidate_object from django_orm.manager import FTSManager as Manager from django.db import models meta_orm_class = getattr(sender, 'OrmMeta', None) if not meta_orm_class: meta_orm_obj = OrmMeta() else: meta_orm_obj = meta_orm_class() options = getattr(meta_orm_obj, 'options', {}) if 'cache_object' not in options: options['cache_object'] = DEFAULT_CACHE_ENABLED if 'cache_queryset' not in options: options['cache_queryset'] = DEFAULT_CACHE_ENABLED if options['cache_queryset']: options['cache_object'] = True if 'default_timeout' not in options: options['default_timeout'] = DEFAULT_CACHE_TIMEOUT meta_orm_obj.options = options sender.add_to_class('_orm_meta', meta_orm_obj) if not getattr(sender, '_orm_manager', None): sender.add_to_class('_orm_manager', Manager()) sender.add_to_class('_get_cache_key_for_pk', staticmethod(lambda x,y: get_cache_key_for_pk(x, y))) sender.add_to_class('cache_key', property(lambda x: x._get_cache_key_for_pk(x.__class__, x.pk)))
def get(self, *args, **kwargs): if not self.cache_object_enable: return super(CachedMixIn, self).get(*args, **kwargs) if len(args) > 0: return super(CachedMixIn, self).get(*args, **kwargs) pk, params, obj = None, copy.deepcopy(kwargs), None if "pk" in params: pk = params.pop('pk') elif "id" in kwargs: pk = params.pop('id') if pk: ckey = get_cache_key_for_pk(self.model, pk, **params) obj = cache.get(ckey) if not obj: obj = super(CachedMixIn, self).get(*args, **kwargs) cache.set(ckey, obj, self.cache_timeout) log.info("Orm cache missing: %s(%s)", self.model.__name__, obj.id) else: log.info("Orm cache hit: %s(%s)", self.model.__name__, obj.id) else: obj = super(CachedMixIn, self).get(*args, **kwargs) return obj
def _get_objects_for_keys(self, model, keys): # First we fetch any keys that we can from the cache results = cache.get_many([get_cache_key_for_pk(model, k) for k in keys]).values() # Now we need to compute which keys weren't present in the cache result_ids = [obj.id for obj in results] missing = [key for key in keys if key not in result_ids] log.info("Orm cache queryset missing objects: %s(%s)", self.model.__name__, missing) # We no longer need to know what the keys were so turn it into a list results = list(results) objects = model._orm_manager.no_cache().filter(pk__in=missing) if objects: cache.set_many(dict([(obj.cache_key, obj) \ for obj in objects]), self.cache_timeout) results.extend(objects) # Do a simple len() lookup (maybe we shouldn't rely on it returning the right # number of objects cnt = len(missing) - len(objects) if cnt: raise CacheMissingWarning("%d objects missing in the database" % (cnt,)) return results
def _get_cache_key_for_pk(model, pk): return get_cache_key_for_pk(model, pk)