给web.py加点仿TG的功能

最近忙,本来计划的一篇技术文章写了很久没写完,先发一篇短文凑数。

以前用Turbogears 1.x的时候觉得它有一些功能真是很方便,比如expose decorator。不过现在用web.py就没有这种东西了。

话说我改用web.py就是图它比较清爽这个优点,但能增加点方便还是好的。其实这个功能实现起来挺简单的,于是这两天就给web.py写了一个。

另外,现在RESTful的API都喜欢提供多种格式的结果返回(貌似这是twitter引领的风潮),于是顺便也给自己写的这个东东增加了这样的功能。

代码如下(其中obj2xml的代码来自这里):

import json
import web
from web.contrib.template import render_mako

class TGBaseHandler: def init(self, templates_path): self.mako_render = render_mako( directories=[templates_path,], input_encoding='utf-8', output_encoding='utf-8' )

# 默认支持两种 format render
# html render 使用 mako 模板
def html_render(self, page, result):
    return getattr(self.mako_render, page)(**result)

def json_render(self, page, result):
    return json.dumps(result)

# 自动调用相应的 format render
def render(self, page, format, result):
    try:
        render_func=getattr(self, format + '_render')
    except AttributeError:
        raise "Invalide render format!"
    return render_func(page, result)

format : html/json/xml…

默认为 html format,只需要提供 page 参数,其它 format 可以不需要 page 参数

def expose(page='', format='html'): def expose_wrapper(fn): def format_wrapper(self, *args, **kwargs): result=fn(self, *args, **kwargs)             if 'format' in result.keys(): # 自动选择相应的 format                 format = result['format']                 del result['format'] return self.render(page, format, result) return format_wrapper return expose_wrapper

用法如下:

#...
import obj2xml

urls = ( "/", "index", "/index", "index", "/jsondata", "jsondata", "/timeline.?([^/?.]+)", "timeline", # 自动取得 format 参数 )

#…

class BaseHandler(TGBaseHandler):     def init(self):         TGBaseHandler.init(self, ‘pathto/templates’) # 初始化 mako

# 可以在这里添加各种自定义的 format render
def xml_render(self, page, result):
    return obj2xml.getXML(result)

class index(BaseHandler): @expose("index") # 默认 format 为 html def GET(self): return dict(url="/")

class jsondata(BaseHandler): @expose(format='json') # 指定用 json format render def GET(self): return dict(tweets=[{'id':'1234','text':'hello'},{'id':'2345','text':'world'}])

class timeline(BaseHandler):     @expose() # 自动选择 format render     def GET(self, format):         return dict(format=format, tweets=[{'id':'1234','text':'hello'},{'id':'2345','text':'world'}]) # 注意,要在这里返回 format 参数

这样访问 index 页面时返回的是用mako render出来的HTML,访问 jsondata 页面返回的就是一个 JSON 文本,访问 timeline.xml 和 timeline.json 就可以分别返回 XML 和 JSON 文本。

另外Turbogears 1.x的identity也很赞,回头有空也弄一个给web.py。

推送到[go4pro.org]