Forcing a view to expire from cache

1,356 views
Skip to first unread message

Maciej Bliziński

unread,
Aug 12, 2006, 3:38:16 PM8/12/06
to django...@googlegroups.com
Hello, Djangoers,

I've got a site where some pages take really long to calculate and
display (~40s), so I've turned on the caching and it works like a
breeze. I'm amazed.

This is a data-analysis site, and after I change some parameters, I want
to clear the cache for one of the views. How can I force a view to
expire?

Reading the docs http://www.djangoproject.com/documentation/cache/ I
think that I need to use the vary_on_headers, but I need to create a
custom header and modify it whenever my data gets modified. I just don't
know how to do it. Can you give me a hint?

--
Maciej Bliziński
http://automatthias.wordpress.com

Don Arbow

unread,
Aug 12, 2006, 4:13:37 PM8/12/06
to django...@googlegroups.com
On Aug 12, 2006, at 12:38 PM, Maciej Bliziński wrote:
>
> This is a data-analysis site, and after I change some parameters, I
> want
> to clear the cache for one of the views. How can I force a view to
> expire?

Take a look at the example just above the "Upstream Caches"
paragraph. It shows how to delete a key (view) from the cache.

http://www.djangoproject.com/documentation/cache/#upstream-caches

Don

Maciej Bliziński

unread,
Aug 12, 2006, 4:48:07 PM8/12/06
to django...@googlegroups.com
On Sat, 2006-08-12 at 13:13 -0700, Don Arbow wrote:
> On Aug 12, 2006, at 12:38 PM, Maciej Bliziński wrote:
> >
> > This is a data-analysis site, and after I change some parameters, I
> > want
> > to clear the cache for one of the views. How can I force a view to
> > expire?
>
> Take a look at the example just above the "Upstream Caches"
> paragraph. It shows how to delete a key (view) from the cache.

Hm... the keys look like:
views.decorators.cache.cache_page.myprefix./myproject/.d41d8cd98f00b204e9800998ecf8427e

It's fine, except the trailing MD5 sum. Is there a way to guess the key
of the view? Otherwise, I could use SQL to find everything that begins
with "views.decorators.cache.cache_page.myprefix./myproject/something/"
and nuke it, but I'd rather stay high-level.

James Bennett

unread,
Aug 12, 2006, 4:54:19 PM8/12/06
to django...@googlegroups.com
On 8/12/06, Maciej Bliziński <maciej.b...@gmail.com> wrote:
> It's fine, except the trailing MD5 sum. Is there a way to guess the key
> of the view? Otherwise, I could use SQL to find everything that begins
> with "views.decorators.cache.cache_page.myprefix./myproject/something/"
> and nuke it, but I'd rather stay high-level.

How is your view retrieving the cached data in the first place, if it
doesn't know the key?

--
"May the forces of evil become confused on the way to your house."
-- George Carlin

ToddG

unread,
Aug 12, 2006, 5:17:51 PM8/12/06
to Django users
Maciej, you mentioned "turned on the caching" -- that sounds like using
the caching middleware, not the view-level cache functionality. Or am I
guessing wrong?

To my understanding if you need to be able to manuallly get and clear
cached pages you'll need to use the view level caching, not the
middleware.

Maciej Bliziński

unread,
Aug 12, 2006, 5:54:49 PM8/12/06
to django...@googlegroups.com
On Sat, 2006-08-12 at 21:17 +0000, ToddG wrote:
> Maciej, you mentioned "turned on the caching" -- that sounds like using
> the caching middleware, not the view-level cache functionality. Or am I
> guessing wrong?

You're guessing right. Sorry for not being specific enough.

> To my understanding if you need to be able to manually get and clear


> cached pages you'll need to use the view level caching, not the
> middleware.

So I switched to per-view caching, according to the docs:
http://www.djangoproject.com/documentation/cache/#the-per-view-cache

from django.views.decorators.cache import cache_page

def slashdot_this(request):
...

slashdot_this = cache_page(slashdot_this, 60 * 15)

I removed the middleware references from the settings.
The keys still look the same, with the MD5-sum at the end. Do I need to
use the cache.set() and cache.get() methods then?

ToddG

unread,
Aug 12, 2006, 6:17:37 PM8/12/06
to Django users
I think I didn't get the whole picture before; reading the docs and
source a bit more, it looks like you can't manually get/set/clear
(decorator) cached views. The view-level decorator basically
applies/restricts the middleware functionality to a specific view
instead of all views (or just excluding admin pages with the built-in
middleware).

What you probably want is the low-level cache API, and use it to store
the results of your long-running calculations. Since you're setting the
entry in the cache the key generation is up to you. So you wont' be
caching at the page or view level, just specific pieces of data that
are resource-intensive, and the view will run on every request.

It's probably not a huge ordeal to extend/rewrite the caching
middleware to respond to signals and let you cache page level and clear
it by sending signals on data updates, but I don't think anything like
this is available out of the box. But maybe it is somehow, I'm not too
familiar with all the innards and parts available... you can see how
Django generates its keys in django.utils.cache.

Maciej Bliziński

unread,
Aug 12, 2006, 7:53:12 PM8/12/06
to django...@googlegroups.com
On Sat, 2006-08-12 at 22:17 +0000, ToddG wrote:
> What you probably want is the low-level cache API, and use it to store
> the results of your long-running calculations. Since you're setting the
> entry in the cache the key generation is up to you. So you wont' be
> caching at the page or view level, just specific pieces of data that
> are resource-intensive, and the view will run on every request.

I tried that and it works, thanks Todd.

Just a small gotcha-remark. I was storing the QuerySets directly after
calling them:

qs = cache.get(mykey)
if not qs:
qs = MyClass.objects.filter(...)
cache.set(mykey, qs, expiration)

And somehow it didn't speed-up the request processing... what was the
problem?

The QuerySets are lazy! I was storing unevaluated QuerySets!
I had a good laugh. :-)

I now store the whole response objects, because I had several expensive
queries and I didn't want to code caching of each of them separately.

Regards,
Maciej

Reply all
Reply to author
Forward
0 new messages