# helperapp\models.py # -*- coding: UTF-8 from django.db import models from django.core.cache import cache class CachedModelManager(models.Manager): def contribute_to_class(self, model, name): super(CachedModelManager, self).contribute_to_class(model, name) setattr(model, 'volatile_cache_keys', getattr(model, 'volatile_cache_keys', [])) setattr(model, 'cache_key', getattr(model, 'cache_key', cache_key)) setattr(model, 'get_cache', getattr(model, 'get_cache', get_cache)) setattr(model, 'set_cache', getattr(model, 'set_cache', set_cache)) setattr(model, 'del_cache', getattr(model, 'del_cache', del_cache)) self._bind_flush_signal(model) def _bind_flush_signal(self, model): models.signals.post_save.connect(flush_volatile_keys, model) def flush_volatile_keys(sender, **kwargs): instance = kwargs.pop('instance', False) for key in instance.volatile_cache_keys: instance.del_cache(key) def cache_key(instance, key): if not instance.pk: name = "%s.%s" % (instance._meta.app_label, instance._meta.module_name) raise models.ObjectDoesNotExist("Can't generate a cache key for " + "this instance of '%s' " % name + "before defining a primary key.") else: return "%s.%s.%s.%s" % (instance._meta.app_label, instance._meta.module_name, instance.pk, key) def get_cache(instance, key): result = cache.get(instance.cache_key(key)) return result def set_cache(instance, key, value, timeout=60*60*24*3): result = cache.set(instance.cache_key(key), value, timeout) return result def del_cache(instance, key): result = cache.delete(instance.cache_key(key)) return result # myapp\models.py # -*- coding: UTF-8 from django.contrib.auth.models import User from django.db import models from helperapp.models import CachedModelManager class Abstract(models.Model): creator = models.ForeignKey(User) cache = CachedModelManager() class Meta: abstract = True class Community(Abstract): members = models.ManyToManyField(User) volatile_cache_keys = ['members_list',] @property def members_list(self): result = self.get_cache('members_list') if not result: result = self.members.all() self.set_cache('members_list', result) return result