Question

I have cache tag in the base template:

{% cache 100000 categories %}
    Categories output
{% endcache %}

When I add new category through Django admin, I want invalidate this cache:

class CategoriesAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        super(CategoriesAdmin, self).save_model(request, obj, form, change)

        cache.delete('categories')

But the cache is stay valid! What is wrong?

Was it helpful?

Solution

That's because the actual key is not "categories", but rather one that's dynamically constructed by Django using the following:

args = md5_constructor(u':'.join([urlquote(resolve_variable(var, context)) for var in self.vary_on]))
cache_key = 'template.cache.%s.%s' % (self.fragment_name, args.hexdigest())

See: https://code.djangoproject.com/browser/django/tags/releases/1.3.1/django/templatetags/cache.py

In general, the key is going to be in the format: template.cache.categories.[hexdigest]. So the tricky part is figuring out the hexdigest part.

I found the following Django snippet (in the comments), which looks like it should still work (from 2009):

from django.core.cache import cache
from django.utils.hashcompat import md5_constructor
from django.utils.http import urlquote

def invalidate_template_cache(fragment_name, *variables):
    args = md5_constructor(u':'.join([urlquote(var) for var in variables]))
    cache_key = 'template.cache.%s.%s' % (fragment_name, args.hexdigest())
    cache.delete(cache_key)

Since you're not passing any variables to vary on to the templatetag, you can call that with just: invalidate_template_cache('categories'). Otherwise, you'd need to pass in a list of all the variables the template tag varies on as the second argument.

OTHER TIPS

In Django 1.6+ please use make_template_fragment_key:

django.core.cache.utils.make_template_fragment_key(fragment_name, vary_on=None) If you want to obtain the cache key used for a cached fragment, you can use make_template_fragment_key. fragment_name is the same as second argument to the cache template tag; vary_on is a list of all additional arguments passed to the tag. This function can be useful for invalidating or overwriting a cached item, for example:

from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
# cache key for {% cache 500 sidebar username %}
key = make_template_fragment_key('sidebar', [username])
cache.delete(key) # invalidates cached template fragment

Works like magic :-)

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