李迎辉 2009年11月04日 星期三 12:23 | 1746次浏览 | 3条评论
在经过对beaker中的session替换之后,我终于又把cache给替换掉了。完全是自个儿重写。一方面它可以象一个dict一样工作,同时可以通过put, get来调用。使用这两个函数的好处就是可以有更多的参数。目前这个类在uliweb/lib/weto/cache.py中。
创建cache
import weto.cache
cache = weto.cache.Cache()
这样可以创建一个cache。因为没有指定Cache类的初始化参数,因此会自动以file格式创建cache。如果需要指定其它的格式和参数,可以设置:
storage_type, options, expiry_time
这三个参数。storage是类型,目前只支持'file', 'dbm', 'database',分别对应三种不同的存储类型。
options则根据不同的类型有所区别,比如'file'类型需要传入'data_dir',用以指定cache保存的路径。而'database'则需要指明要使用的表名和数据库连接的一些信息。
expiry_time是指定缺省的超时时间。这是当你在put时没有指定超时时间时使用的,在调用put时可以单独设定。
cache.get(key)
这样的调用,如果key不存在,或超时则会引发一个异常抛出CacheKeyException异常。
如果不想引发异常,则可以:
cache.get(key, default)
其中default不能为None,这样当key不存在,则不会引发异常,返回default值。如果为None,则同get(key)的效果。
cache.put(key, value, expire=None)
这样可以设置一个cache。如果expire没有传入则使用缺省的超时时间。时间以秒为单位。
同时为了方便函数的封装,还提供了
cache.cache(key=None, expire=None)
这个decorator。例如:
@cache.cache(expire=15)
def f(*args, **kwargs):
或
@cache.cache(key, expire=15)
def f(*args, **kwargs):
这两种都是可以的,区别在于前一个没有key参数,那它将根据函数名和参数来生成一个key,而后面则是由用户主动指定了一个key。
在进行上进的改造之后,原来的beaker就删除了,这样uliweb中不再使用beaker了。同时对原uliweb.contrib.cache进行了修改,去掉了middle_cache.py,而采用让用户自行调用的机制。同时为了同app的配置功能相结合和方便用户使用,在uliweb/utils/cache.py中编写了一个get_cache()的函数,同时对Cache类的增加了page方法。
get_cache()可以自动从settings中找到相应的配置。目前主通过两个secion来控制的:
[CACHE]和[CACHE_STORAGE],前者用来控制cache的类型和超时时间。后者是用来针对每一种类型来设置与存储相关的配置信息。在调用get_cache()时,你还可以传入一些参数,它的原型是:
def get_cache(cache_setting_name='CACHE', cache_storage_setting_name='CACHE_STORAGE'):
即可以指明使用其它的配置名,这样就可以在你的settings.ini中存放不同的cache的配置,通过get_cache来使用不同的cache机制。
为什么要对Cache进行扩展,Cache.cache原来是针对函数本身和它的参数,但是这样对于view有一点问题。有些view可能通过QUERY_STRING来处理不同的传入参数,因此在url上它们不同,但是在view函数上是完全一样,因此这种只根据函数本身和参数是有问题的。因此扩展的page这个decorator使用了request.url值,它是一个完整的访问路径,包括了QUERY_STRING信息。因此为了生成静态cache,可以使用改造后的Cache类。当你调用get_cache()时返回的cache对象已经是使用了这个新的Cache类了。
所以为了方便和更适合在Uliweb环境下使用,可以使用uliweb.utils.cache的get_cache()函数。例如:
from uliweb.utils.cache import get_cache()
cache = get_cache() #使用缺省的settings.ini设置。因此需要加入uliweb.contrib.cache这个app
@cache.cache(expire=15)
@expose('/index')
def index():
return {}
现在我把uliwebproject也添加了cache的支持,不过发现的问题是,不能简单的使用@cache.page()来对view方法进行处理。原因是:
在view方法中有对cookie的处理,采用cache的方式会屏蔽掉这块处理
因此在uliwebproject中并不是使用的decorator的方式,而是在view中对可以cache化的部分进行了手工处理,如:
cache = get_cache()
@cache.cache(_f)
def f():
content = file(_f).read()
if render:
content = to_html(template(content, env=application.get_view_env()))
else:
content = to_html(content)
return application.template('show_document.html', locals())
response.write(f())
return response
Zeuux © 2024
京ICP备05028076号
回复 邢兴 2009年11月10日 星期二 09:50
用不同的 cache saver 来实现实际的存储,然后用 saver.install() 安装不同的 saver 来实现不同的调用。
这样,在切换不同的 cache 的时候,不
根据接口
回复 李迎辉 2009年11月10日 星期二 11:29