Improving Django Cache – Part II

In part I of this series we setup a custom django cache backend based on the current memcached implementation. For the second installment in this series we are going to start modifying our custom cache backend.

Memcached has a couple of limitations it sets on keys. Currently the length limit of a key is set at 250 characters and the key must not include control characters or whitespace. These limitations can be a problem when dealing with long permalinks or rendered template nodes. First thing we need to do is create a method that will fix keys.

def fix_key(self, key):
    from django.utils.encoding import smart_str
    import md5

    cache_key = re.sub(r'\s+', '-', key)
    cache_key = smart_str(cache_key)
    if len(cache_key) > 250:
        cache_key = cache_key[:200] + '-' + md5.new(cache_key).hexdigest()
        return cache_key

This method will replace whitespaces with dashes and limit the key length so that it never exceeds the 250 limit set by memcached. Now we just have to change the methods on CacheClass so that they call fix_key and pass the newly generated key into memcached calls.

The method get_many takes some special consideration. This method takes a list of keys and returns a dictionary of key value pairs. This means fix_key needs to be called on all keys passed into the list. Memcached will return a dict with the fixed keys so they must be translated back to the original keys.

def get_many(self, keys):
    fixed_keys = map(self.fix_key, keys)
    cache_dict = self._cache.get_multi(fixed_keys)
    final_dict = {}
    for fixed_key, value in cache_dict.iteritems():
        key = keys[fixed_keys.index(fixed_key)]
        final_dict[key] = value
    return final_dict

Now your shouldn’t have to worry about cache keys in your django application. Continue on to part III