Using beaker cache with pyramid

425 views
Skip to first unread message

Massimiliano Torromeo

unread,
Dec 11, 2010, 10:10:42 AM12/11/10
to pylons-devel
Hi,
I'm building a new website using pyramid for the first time.
I have some experience with pylons and I'm finding some utilities I
was using with pylons are missing in pyramid.
Up till now I was able to reimplement most of what I needed, but I'm
having trouble understanding what is the right way to integrate the
beaker caching system inside my application.
I am already using the pyramid_beaker session factory, but there
doesn't seem to exist a beaker cache factory (or a valid alternative).

Are there any plans for such a feature?
How should I proceed to implement it myself?

I think I probably should define my own "request factory", so that I
can create custom requests with a request.cache property but I'm not
sure if it's the right thing to do and I need some pointers.

Any help is much appreciated.

Thanks.

Wichert Akkerman

unread,
Dec 11, 2010, 1:14:01 PM12/11/10
to pylons...@googlegroups.com
On 2010-12-11 16:10, Massimiliano Torromeo wrote:
> I am already using the pyramid_beaker session factory, but there
> doesn't seem to exist a beaker cache factory (or a valid alternative).

No factory is needed. Here is my recipe:

from beaker.util import parse_cache_config_options
import beaker.cache

settings=config.registry.settings
cfg=parse_cache_config_options(settings)
beaker.cache.cache_regions.update(cfg["cache_regions"])


after putting that in your startup code in run.py you can use the beaker
cache_regions decorator for normal caching.

Wichert.

--
Wichert Akkerman <wic...@wiggy.net> It is simple to make things.
http://www.wiggy.net/ It is hard to make things simple.

Massimiliano Torromeo

unread,
Dec 11, 2010, 1:34:24 PM12/11/10
to pylons...@googlegroups.com
I don't have a run.py.
Should I put it in the main function in __init__.py?

I tried my idea anyway, even if it didn't seem the correct way to do
it (I learned something at least), and it works:

# pyramid_beaker_cache/__init__.py
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options
from pyramid.request import Request

def BeakerCacheRequestFactory(**options):
class BeakerCacheRequest(Request):
_cache_options = options
_cache = None

@property
def cache(self):
if self._cache is None:
self._cache = CacheManager(**self._cache_options)
return self._cache
return BeakerCacheRequest

def request_factory_from_settings(settings):
""" Return a Pyramid request using Beaker cache settings
supplied from a Paste configuration file"""
options = parse_cache_config_options(settings)
return BeakerCacheRequestFactory(**options)

# application/__init__.py
# [...]
config = Configurator(settings=settings)
request_factory = request_factory_from_settings(settings)
config.set_request_factory(request_factory)
# [...]

And then I use the cache.region decorator:
@self.request.cache.region('short_term', 'something')

It works, but I will try your method next.
Thanks.

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

Daniel Holth

unread,
Dec 11, 2010, 1:49:28 PM12/11/10
to pylons...@googlegroups.com
Massimiliano,

I went down the same path of looking for a per-request caching middleware that worked in the same way as the session middleware. Eventually I decided caching was not tied to a single request in the same way as a session, so I have a global cache as Wichert suggests.

Daniel

Jerry

unread,
Dec 11, 2010, 11:09:04 PM12/11/10
to pylons-devel
Hi,

I tried the Wichert's configuration and declared my view --

@cache.cache_region('long_term')
def home_view(request):

but got an error --

File '/home/virtualenv/lib/python2.6/site-packages/Beaker-1.5.4-
py2.6.egg/beaker/cache.py', line 114 in cached
return cache[0].get_value(cache_key, createfunc=go)
File '/home/virtualenv/lib/python2.6/site-packages/Beaker-1.5.4-
py2.6.egg/beaker/cache.py', line 214 in get
return self._get_value(key, **kw).get_value()
File '/home/virtualenv/lib/python2.6/site-packages/Beaker-1.5.4-
py2.6.egg/beaker/container.py', line 298 in get_value
v = self.createfunc()
File '/home/virtualenv/lib/python2.6/site-packages/Beaker-1.5.4-
py2.6.egg/beaker/cache.py', line 112 in go
return func(*args)
TypeError: home_view() takes exactly 1 argument (2 given)

The unwanted argument is in fact a traversal context object --

>>> args
(<pyramid.traversal.DefaultRootFactory instance at 0xaa67e2c>,
<Request at 0xaa67e0c GET http://localhost:6543/>)

How does beaker cache work with Pyramid?

Thanks.

Jerry

Daniel Holth

unread,
Dec 12, 2010, 2:45:23 PM12/12/10
to pylons...@googlegroups.com
Pyramid calls a view with the request if it accepts one positional argument, but the cache decorator hides the function's signature so Pyramid passes the context and the request.

If you change your view to

def home_view(context, request):
    pass

It will probably do something. However, str(context) and str(request) will be part of the cache key, including all the browser headers, which may not be what you want. It probably makes more sense to cache the results of functions called by the view.

Daniel

Jerry

unread,
Dec 12, 2010, 9:21:42 PM12/12/10
to pylons-devel
Thanks for the tip.

However, the ultimate goal is to cache the template output (e.g., I
choose Genshi for its power at some expense of speed) and I'm sure
many people would want to know how to juggle Pyramid/Beaker/XTemplate
to make it work.

Jerry
Reply all
Reply to author
Forward
0 new messages