Correction re: Django caching
March 2, 2010
OK, so after reading the Django source code a little more closely, I found I was wrong. It absolutely is possible to invalidate the per-view caching. Here's a function I wrote to do it:
def expire_view_cache(view_name, args=[], namespace=None, key_prefix=None):
"""
This function allows you to invalidate any view-level cache.
view_name: view function you wish to invalidate or it's named url pattern
args: any arguments passed to the view function
namepace: if an application namespace is used, pass that
key prefix: for the @cache_page decorator for the function (if any)
"""
from django.core.urlresolvers import reverse
from django.http import HttpRequest
from django.utils.cache import get_cache_key
from django.core.cache import cache
# create a fake request object
request = HttpRequest()
# Loookup the request path:
if namespace:
view_name = namespace + ":" + view_name
request.path = reverse(view_name, args=args)
# get cache key, expire if the cached item exists:
key = get_cache_key(request, key_prefix=key_prefix)
if key:
if cache.get(key):
cache.set(key, None, 0)
return True
return False
You can use it like this:
from project_utils import expire_view_cache
def invalidate_blog_index(sender, **kwargs):
"""Invalidate the view-level cache for the blog:index page"""
expire_view_cache("index", namespace="blog")
post_save.connect(invalidate_blog_index, sender=Entry)
The is a pretty naive example, but basically whenever a blog entry is saved, the view-level cache for the blog index page is invalidated. Obviously you could be much more sophisticated with this. Per-view caching aside, I am quite sure that template fragment caching can only be invalidated when the TTL expires. That's a shame, but the per-view caching is far more useful anyway in my opinon.