9

I have the following in my ini file:

cache.regions = default_term, second, short_term, long_term
cache.type = memory
cache.second.expire = 1
cache.short_term.expire = 60
cache.default_term.expire = 300
cache.long_term.expire = 3600

And this in my __init__.py:

from pyramid_beaker import set_cache_regions_from_settings
set_cache_regions_from_settings(settings)

However, I'm not sure how to perform the actual caching in my views/handlers. Is there a decorator available? I figured there would be something in the response API but only cache_control is available - which instructs the user to cache the data. Not cache it server-side.

Any ideas?

dave
  • 7,717
  • 19
  • 68
  • 100
  • I'm still not sure about this myself. I've set the values in my ini file and set the cache regions from the settings, but no cache regions seem to be available if I do something like `print cache.cache_regions` in my view. It would appear the settings are not getting passed to the view. It seems like the cache parts of pyramid_beaker are not quite ready for prime-time... – zeitkunst Aug 14 '11 at 18:51

5 Answers5

12

My mistake was to call decorator function @cache_region on a view-callable. I got no error reports but there were no actual caching. So, in my views.py I was trying like:

@cache_region('long_term')
def photos_view(request):
    #just an example of a costly call from Google Picasa
    gd_client = gdata.photos.service.PhotosService()
    photos = gd_client.GetFeed('...')
    return {
        'photos': photos.entry
    }

No errors and no caching. Also your view-callable will start to require another parameter! But this works:

#make a separate function and cache it
@cache_region('long_term')
def get_photos():
    gd_client = gdata.photos.service.PhotosService()
    photos = gd_client.GetFeed('...')
    return photos.entry

And then in view-callable just:

def photos_view(request):
    return {
        'photos': get_photos()
    }

The same way it works for @cache.cache etc.

Summary: do not try to cache view-callables.

PS. I still have a slight suspiction that view callables can be cached :)

UPD.: As hlv later explains, when you cache a view-callabe, the cache actually is never hit, because @cache_region uses callable's request param as the cache id. And request is unique for every request.

yentsun
  • 2,488
  • 27
  • 36
6

btw.. the reason it didnt work for you when calling view_callable(request) is, that the function parameters get pickled into a cache-key for later lookup in the cache. since "self" and "request" change for every request, the return values ARE indeed cached, but can never be looked up again. instead your cache gets bloated with lots of useless keys.

i cache parts of my view-functions by defining a new function inside the view-callable like

    def view_callable(self, context, request):

        @cache_region('long_term', 'some-unique-key-for-this-call_%s' % (request.params['some-specific-id']))
        def func_to_cache():
            # do something expensive with request.db for example
            return something
        return func_to_cache()

it SEEMS to work nicely so far..

cheers

hlv
  • 1,087
  • 8
  • 6
  • I guess this is the clue to my case (why not try caching view callables directly). Thanks very much, that explains everything :) – yentsun Apr 15 '12 at 20:58
4

You should use cache region:

from beaker.cache import cache_region

@cache_region('default_term')
def your_func():
    ...
Blaise Laflamme
  • 456
  • 5
  • 4
  • What if I want to use cache without cache_region? @cache.cache doesn't work for me, it wants a CacheManager instance. – jeffcook2150 Aug 10 '11 at 12:17
2

A hint for those using @cache_region on functions but not having their results cached - make sure the parameters of the function are scalar.

Example A (doesn't cache):

@cache_region('hour')
def get_addresses(person):
    return Session.query(Address).filter(Address.person_id == person.id).all()

get_addresses(Session.query(Person).first())

Example B (does cache):

@cache_region('hour')
def get_addresses(person):
    return Session.query(Address).filter(Address.person_id == person).all()

get_addresses(Session.query(Person).first().id)

The reason is that the function parameters are used as the cache key - something like get_addresses_123. If an object is passed this key can't be made.

Ross
  • 46,186
  • 39
  • 120
  • 173
1

Same problem here, you can perform caching using default parameters with

from beaker.cache import CacheManager

and then decorators like

@cache.cache('get_my_profile', expire=60)

lik in http://beaker.groovie.org/caching.html, but I can't find the solution how to make it work with pyramid .ini configuration.

Uznick
  • 11
  • 1