TechLife devBlog

Marzec 2011

Django: usuwanie cache'u generowanego przez szablon

Kodowanie, Django, Techblog 25 marca 2011 23:58

Sytuacja jest następująca: 1989 rok, Kijów. Piękna ukraińska jesień. Czterech urodzonych morderców, uzbrojonych po zęby, a ja sam, jeden, z moim wiernym kałachem... mamy jakiś kawałek szablonu, którego wygenerowanie kosztuje nas sporo zasobów np. wiele zapytań do bazy. Cache'ujemy więc w szablonie wygenerowany HTML aby ulżyć serwerowi. Np. tak:

{% load cache %}

{% cache 604800 statystyki %}
   jakiś super zasobożerny w generowaniu kod HTML
{% endcache %}

Wszystko działa ładnie. Cache wygasa co tydzień (604800 sekund) i wszystko gra. Problem pojawia się jednak, kiedy wygenerowany kod zależy bezpośrednio od jakiegoś obiektu lub obiektów. Kiedy dany obiekt jest modyfikowany chcielibyśmy usunąć cache generowany przez szablon. Rozwiązanie wydaje się być dość logiczne:

from django.core.cache import cache

cache.delete('statystyki')

Niestety powyższy kod robi nic. Template tag tworzy cache generując klucz:

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())

Jak widzimy schemat jest następujący:
template.cache.KLUCZ-Z-SZABLONU.ZAKODOWANE_ARGUMENTY

Jeżeli nie używaliście argumentów w szablonie przy stworzeniu klucza cache'u (czyli nie zrobiliście np. czegoś takiego: {% cache 604800 statystyki request.user %}) to Wasza lista argumentów będzie pusta. Suma MD5 z pustego stringa zawsze wynosi tyle samo, więc dla cache'u tworzonego bez argumentów klucz jest stały i wygląda tak:

cache.delete('template.cache.statystyki.d41d8cd98f00b204e9800998ecf8427e')