Skip to content

Instantly share code, notes, and snippets.

@eculver
Created April 20, 2010 17:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save eculver/372823 to your computer and use it in GitHub Desktop.
Save eculver/372823 to your computer and use it in GitHub Desktop.
A generic cache manager
import random
from django.db import models
from django.core.cache import cache
class CacheManager(models.Manager):
'''Generic Cache Manager based on the concept of generator ids to
handle invalidation of collections.
'''
def _test_model(self, obj):
''' Checks to see if the current object is up-to-date with it's model.
Returns True if it is, otherwise False.
Used to tell if an object fetched from cache is fresh.
'''
# Duct tape way to make the conditionals work
if obj is None:
return False
# Compares the object to a blank version of the model
res = dir(obj)==dir(obj.__class__())
return res
def _get_model_string(self):
''' Return the correct string for a given model. '''
return self.model.__name__.lower()
def _get_generator_id(self):
''' Return the generator id for a given model.
This is used for getting and invalidating collections.
<model_name>-generator_id -> generator_id
<model_name>-<generator_id> -> <collection>
On save, save new generator id, auto-invalidates all collections.
Generator id is just a random 5-digit number.
'''
key = "%s-generator_id" % self._get_model_string()
generator_id = cache.get(key)
if not generator_id:
cache.set(key, int(random.random() * 100000), 60 * 60 * 48) # 48 hours.
return generator_id
def get(self, **kwargs):
''' Return the object by id. Sets it into cache. If no object is
found, returns None.
'''
key = self._get_model_string()
for k,v in kwargs.iteritems():
key = "%s:%s:%s" % (key, k, v)
object = cache.get(key)
if not object or not self._test_model(object):
try:
object = super(CacheManager, self).get(**kwargs)
cache.set(key, object, 60 * 60 * 24)
except self.model.DoesNotExist:
object = None
return object
def filter(self, **kwargs):
''' Try to get a bunch of objects from cache.
Uses generator_id and signals to make sure that it's getting the
most up to date collection. On save, a new generator_id is
generated.
'''
key = "%s-%s" % (self._get_model_string(), self._get_generator_id())
for k,v in kwargs.iteritems():
key = "%s:%s:%s" % (key, k, v)
objects = cache.get(key)
if not objects:
objects = super(CacheManager, self).filter(**kwargs)
cache.set(key, objects)
return objects
def all(self):
''' Try to get all objects from cache. '''
key = "%s:all" % self._get_model_string()
objects = cache.get(key)
if not objects:
objects = super(CacheManager, self).all()
cache.set(key, objects)
return objects
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment