Tuesday, February 28, 2012

cache template tag with an model instance as argument

Hello,

I'm having a weird behavior with the {% cache %} template tag. I'm
using something like this:

{% get_current_language as LANGUAGE_CODE %}
{% cache CACHE_MIDDLEWARE_SECONDS request.user.username post LANGUAGE_CODE %}

Where post is an instance of my own model Post (I'm using
django-cache-machine[0] to cache querysets):

class Post(caching.base.CachingMixin, models.Model):
....
objects = caching.base.CachingManager()
....

The problem is that "sometimes" (I'm not sure when yet) Django renders
the same chunk of HTML code for different Posts. I can "fix" this
changing "post" by "post.id" but there are other cases when this "fix"
is not possible: with an object_list of Post for example.

I was taking a look at the source code of the cache template tag:
https://code.djangoproject.com/browser/django/tags/releases/1.3.1/django/templatetags/cache.py
and I found that it uses a wrapper of the function urllib.quote from
the standard lib:
https://github.com/python-git/python/blob/master/Lib/urllib.py#L1181

... meanwhile I was writing this email ...

The instance object is converted to a string before send it to the
urllib.quote function. So, if there are two (or more) instance that
have the same unicode representation the "cache" templatetag will
fail.

So, I think the key should be generated with something else, something
like a hash, a md5 of pickled instance or something like that. I don't
know, I'm not a ninja on these topics:

A working example of my thoughts could be something like this:

>>> from django.utils.hashcompat import md5_constructor
>>> import pickle
>>> md5_constructor(pickle.dumps(Post.objects.filter(title='Same Title')[0])).hexdigest() == md5_constructor(pickle.dumps(Post.objects.filter(title='Same Title')[1])).hexdigest()
False

What do you think?

[0] https://github.com/jbalogh/django-cache-machine

--
Kaufmann Manuel
Blog: http://humitos.wordpress.com/
PyAr: http://www.python.com.ar/

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment