Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save douglasgoodwin/377354 to your computer and use it in GitHub Desktop.
Save douglasgoodwin/377354 to your computer and use it in GitHub Desktop.
A generic cache manager
from django.db.models.query import QuerySet
from django.core.cache import cache
from django.db import models
import random
# douglas goodwin 4/2010
# eculver's code with a couple of fixes and instructions
#
# maybe not the nest way to do it but...
#
# paste this into a file called cachemanager.py on your django path
# in your models.py file:
#
# from cachemanager import CacheManager
#
# then:
# Class BlahBlah(models.Model):
# ...
# objects = CacheManager()
#
# then, in your views.py the usual business:
# allblahblah = BlahBlah.objects.all()
class CacheManager(models.Manager):
def _test_mymodel(obj, *args):
''' 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.
NOTE: changed method name to avoid namespace collision (DGOODWIN 7/2010)
NOTE: Added *args to trap instances where too many args have been passed (DGOODWIN 7/2010)
'''
# Duct tape way to make the conditionals work
if len(args) > 0:
return False
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_mymodel(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