django cache invalidation
I use the Django cache middleware on this site. When I used to make a change to a post, or create a new post, the change would not show up until the cache times out for the /blog/ page....until today.
I found a way to invalidate the cache (delete entries) upon the save of an element in my model. When I create a new page, or modify an existing page, the /blog/ index is automatically un-cached. The next hit to the /blog/ page regenerates the cache. yay!
Here is a snippet from my model. The non-relevant code is removed. See the magic..
from django.core.cache import cache
class Post(models.Model):
...<snip>....
def save(self):
self.html = markdown(self.content)
cache_prefix = 'views.decorators.cache.cache_page.cwx.'
cache_postfix = '.d41d8cd98f00b204e9800998ecf8427e'
# delete post cache itself
cache.delete('%s%s%s' % (cache_prefix,self.get_absolute_url(),cache_postfix))
# delete /blog/ cache
cache.delete('%s%s%s' % (cache_prefix,'/blog/',cache_postfix))
cache.delete('%s%s%s' % (cache_prefix,'/rss/blog/',cache_postfix))
cache.delete('%s%s%s' % (cache_prefix,'/atom/blog/',cache_postfix))
super(Post, self).save()
....<snip>.....
It isn't very pretty, but it works. The cache_postfix, is an md5sum of the client request headers. Since the client request headers for the page in the cache framework, are "", the md5sum is always the same there. I just add the file prefix and then invalidate the pages I want.
If cache.delete is called to remove a page that isn't cached (the cache file doesn't exist), it silently does nothing. It doesn't hurt to call it again if the page hasn't been cached between edits.
I will refactor the code pretty soon, to generalize it more. I want to use the permalink Django helper to remove the hard coded url values, and use the routes to generate those on the fly. That way if I change the paths at some point in the future, I won't have to go back and edit this code. It will just keep working, which is a Good Thing (tm).
I looked for a cleaner way to get the cache_prefix, and the cache_postfix, but I haven't found one yet.