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-16

人们研究android的热情高涨

短短一天时间,又有很多新情况发生。

首先,有人测试了汉字的显示,发现可以支持。我也在模拟器里试了一下,确实很容易。系统内带了几种字体,其中有一款支持CJK字符。

其次,有人成功编译了c版本的hello world,并执行成功。使用的是arm的编译器。而且还编译了全功能的busybox,可以安装到模拟器的系统中。

另外,已经有人成功编译linux放入android模拟器中运行。

邮件列表里很多人都在打听、讨论能不能用C/C++/Python/Ruby之类的语言代替java来开发。今天去jython的项目主页看了看,惊奇的发现项目复苏了,jython 2.2已经正式发布。期待高手把jython打包集成进android吧。

2007-11-15

Django+Cheetah

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

从编写者的舒适角度来看,zpt等类似php的语法写起来感觉都恩罗唆,逻辑之外要码的累赘字符太多了,不够爽快。类似webpyCheetah的模板用起来更简单,而且有着类似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')

Dell 640m的双显示器配置

参考了一下Ubuntu论坛里一个帖子,配置好了双显示器,也算是把多出来的一个显示器利用上了。这里是xorg.conf的后半部分:

Section "Device"
BoardName "945 GM"
BusID "0:2:0"
Driver "i810"
Identifier "Device[1]"
Option "MonitorLayout" "CRT,LFP"
Screen 1
VendorName "Intel"
EndSection

Section "Device"
BoardName "945 GM"
BusID "0:2:0"
Driver "i810"
Identifier "Device[0]"
Screen 0
VendorName "Intel"
EndSection

Section "Monitor"
DisplaySize 340 270
Identifier "Monitor[0]"
ModelName "DELL 1708FP"
VendorName "DELL"
Option "DPMS"
HorizSync 31-80
VertRefresh 56-75
EndSection

Section "Monitor"
DisplaySize 305 230
Identifier "Monitor[1]"
ModelName "DELL 1280X800 LAPTOP"
VendorName "DELL"
Option "DPMS"
HorizSync 30-67
VertRefresh 30-60
EndSection

Section "Screen"
Device "Device[0]"
Identifier "Screen[0]"
Monitor "Monitor[0]"
DefaultDepth 24
SubSection "Display"
Modes "1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"
EndSubSection
EndSection

Section "Screen"
Device "Device[1]"
Identifier "Screen[1]"
Monitor "Monitor[1]"
DefaultDepth 24
SubSection "Display"
Modes "1280x800" "1024x768" "800x600" "640x480"
EndSubSection
EndSection

Section "ServerLayout"
Identifier "Default Layout"
InputDevice "Generic Keyboard"
InputDevice "Configured Mouse"
Option "Clone" "off"
Option "Xinerama" "on"
Screen "Screen[1]" leftof "Screen[0]"
Screen "Screen[0]"
InputDevice "Synaptics Touchpad"
InputDevice "stylus" "SendCoreEvents"
InputDevice "cursor" "SendCoreEvents"
InputDevice "eraser" "SendCoreEvents"
EndSection

Section "DRI"
Mode 0666
EndSection

Xinerama模式非常好用,笔记本屏幕的和外接的DELL LCD显示器都可以打到最大分辨率;如果按ctrl_alt_"num +"或者ctrl_alt_"num 1",还可以即时切换鼠标指针所在屏幕的分辨率,在外接投影仪时很方便。让我很纳闷的是,配置里“Screen "Screen[0]"”这一句必须写在screen[1]的后面,不知道是什么原因。

2007-11-14

android真是热火朝天呀

才一天,androidgoogle group里就600多主题了。可惜blogsearch.google.com里还现在搜不到任何andriod主题的blog文章,但我已经四处看到不少文章了。我也下载了一个sdk,用起来很不错。模拟器是基于qemu的,速度很快。不过浏览豆瓣会有文字重叠或者被压缩成条的问题,跟豆瓣的css和 layout table有很大关系,看来要改善在手机的webkit浏览器上的效果,豆瓣还要做很多努力。

google groups里有人在问,能不能用python语言来做开发。但从架构来看,官方会提供的应该只有java。所以有人建议用jython来做,一样能访问所有的api,这个主意倒是不错,但jython项目现在还活跃吗?用五六年前的python语法和类库来开发程序,还是让我死了好啦。

不知道有没有提供像XIM之类的输入法api,但是既然和中国电信、日本docomo这些公司合作,应该会有人在做CJK的输入法吧?可是对他们的开发出来东西的质量表示怀疑,各个智能手机平台上好用的中文输入法大多是个人开发的,这个功能需要好的用户体验才能,这些大公司往往欠缺的就是替用户着想的能力或说是动力。