显示标签为“django”的博文。显示所有博文
显示标签为“django”的博文。显示所有博文

2007-11-30

用于django中的缓存decorator

myproject/decorators.py代码:
from django.core.cache import cache

def cached(cache_key='', timeout_seconds=1800):
def _cached(func):
def do_cache(*args, **kws):
if isinstance(cache_key, str):
key = cache_key % locals()
elif callable(cache_key):
key = cache_key(*args, **kws)
data = cache.get(key)
if data: return data
data = func(*args, **kws)
cache.set(key, data, timeout_seconds)
return data
return do_cache
return _cached
只能用于静态数据的缓存,如果需要对connection.cursor等对象进行缓存,那需要函数本身做更多的处理,不是这个decorator要解决的问题。

使用范例1,简单的cache key:
from myproject.decorators import cached

class MenuItem(models.Model):
@classmethod
@cached('menu_root')
def get_root(self):
return MenuItem.objects.get(pk=1)

使用范例2,cache key需要根据调用参数来决定:
@cached(lambda u: 'user_privileges_%s' % u.username, 3600)
def get_user_privileges(user):
#...

使用范例3,需要只对直接调用者做缓存,递归的调用不需要,那么把要递归函数独立出来:
class MenuItem(models.Model):
@cached(lambda s,u: 'user_menu_%s_%s' % (u.username, s.id), 3600)
def permit_menu_items(self, user):
return self._permit_menu_items(user)

def _permit_menu_items(self, user):
items = []
for mi in self.children():
items += [n for n in mi._permit_menu_items(user)]
return items

使用范例4,返回结果中部分需要做缓存的,首先把要缓存的部分extract出来,然后对其应用缓存机制:
class Report:
def get_summary(self, day, path='', sort='path', type='daily'):
data = self._get_summary(day, path, type)
# sort ...
return data

@cached(lambda s,d,p,t:'summary_%s_%s_%s'%(d,p,t), 3600*24)
def _get_summary(self, day, path='', type='daily'):
#...

2007-11-15

Django+Cheetah

最近在用Django做东西,考虑到现在的流行程度,用Django在稳定性、bug修正速度、参考资料等方面很有优势。但它的模板系统很被一些人诟病,很多用python开发者第一次使用Django都会对它发点牢骚。Python语言的魅力之一就是它的开发,甚至对象实例在运行中都可以随时被改变。但Django因为一些考虑,人为的限制了模板系统的功能,不允许它过于强大。作为一种设计思想,增加限制可以简化问题的复杂程度、提高效率和代码安全性等等,好处不少。但我们是Python程序员,不受拘束、流畅而连贯的书写代码是我们的一贯风格(或说是追求目标),反正我可不愿被当孩子一样限制不许做这、不许做那。用最快的速度,写出糟糕但是能运行的代码,也是程序员应该争取的一个权利--有了可以跑的代码,才能有生存的机会,才能有后续的优化。所以我要寻找一种Django模板的替换方案。

从编写者的舒适角度来看,zpt等类似php的语法写起来感觉都恩罗唆,逻辑之外要码的累赘字符太多了,不够爽快。类似webpy、Cheetah的模板用起来更简单,而且有着类似python的语法风格,个人比较喜欢。据测试,Cheetah的速度也非常快,历史又很悠久,社区活跃,使用起来基本没有后顾之忧。所以我选择Cheetah。参考了Eric Florenzano的文章,在Django中使用Cheetah非常简单。首先要在settings.py中配置模板目录:
TEMPLATE_DIRS = (
'/path/to/myproject/templates',
)

然后编写一个使用Cheetah模板的render_to_response函数,用来代替Django自带的:
import os.path
from Cheetah.Template import Template
from django.conf import settings
from django.http import HttpResponse

def render_to_response(template_name, context=None, **kwargs):
for template_dir in settings.TEMPLATE_DIRS:
path = os.path.join(template_dir, template_name)
if os.path.exists(path):
template = Template(file = path, searchList = (context,))
return HttpResponse(unicode(str(template), 'utf-8'), **kwargs)
raise ValueError, 'Could not find template for %s' % template_name

我是把上面这段代码放在myproject/shortcuts.py文件中。使用起来是这样子:
from myproject.shortcuts import render_to_response
def index(request):
return render_to_response('index.tmpl', {'title': 'index')