Question

I’ve developed a Django site. There’s pretty much a 1-to-1 relationship between model instances in the dabatase, and pages on the site.

I’d like to cache each page on the site (using memcached as the cache back-end). The site isn’t too big — according to a back-of-an-envelope calculation, the whole thing should fit into a fairly small amount of RAM — and the data doesn’t change particularly frequently, so the entire site could effectively live in the cache.

However, when the data does change, I want the cache to reflect that immediately, so ideally I’d like each model instance to be able to clear its own page from the cache when saved.

The way I imagined I’d do that is to cache pages with their URL as the key. Then each model instance can use its URL (which it knows via get_absolue_url()) to clear its page from the cache.

Can I make Django’s per site caching mechanism use page URLs as the cache key?

Was it helpful?

Solution

I don't know of any option to control the cache key, and the implementation in Django doesn't suggest there is any. The code to generate the cache key for a request through the cache middleware lives in django.utils.cache.get_cache_key (to know where to fetch from the cache) and learn_cache_key (to know where to set the cache). You could monkey-patch these functions not to take headers into account like this:

from django.utils import cache
from django.conf import settings

def get_path_cache_key(request, key_prefix=None):
    if key_prefix is None:
        key_prefix = settings.CACHE_MIDDLEWARE_KEY_PREFIX
    return cache._generate_cache_key(request, [], key_prefix)
    # passing an empty headerlist so only request.path is taken into account

cache.get_cache_key = get_path_cache_key
cache.learn_cache_key = get_path_cache_key

This will internally take an MD5 hash of the path, add a potential prefix, and also take the current locale (language) into account. You could further change it to omit the prefix and the language. I would not recommend using the plain path without hashing it, as memcached does not allow keys longer than 250 characters or containing whitespaces, according to the documentation. This should not be a problem because you can just apply get_path_cache_key to the URL from get_absolute_url() as well and clear that page.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top