Genshi笔记(续)

前文见《Genshi笔记》。

这一年多来做了几个小的WEB应用,都是用的Genshi,总体感觉还不错,不过真要系统地写点什么,貌似也写不出来,只能做点笔记了。

一、输出XHTML:

Genshi默认是输出HTML的,作XHTML校验时不能通过,但Genshi是支持输出为XHTML的。

在TurboGears里的设置是在 app.cfg 配置文件里:

tg.defaultview = "genshi"
genshi.default_doctype = 'xhtml-transitional'
genshi.outputformat = 'xhtml'

主要是后面两行的参数设置指定Genshi输出XHTML。

类似的在Pylons里设置也差不多,不过是在 environment.py 文件里:

    # Customize templating options via this variable
tmpl_options = config['buffet.template_options']
tmpl_options['genshi.default_doctype'] = 'xhtml-transitional'
tmpl_options['genshi.default_format'] = 'xhtml'

同样是两个参数的设置。

二、输出XML内容:

在一个应用中需要输出RSS,本来是用 RSS2Gen 库生成静态文件的,但是有些情况还是动态输出为好,于是就用Genshi做了一个。

以TurboGears为例,在 controllers.py 用一个 @expose 函数输出数据:

    @expose(template="myproj.templates.rssfeed",content_type='text/xml; charset=utf-8')
def rssfeed(self, *args, **kw):
data = ...
return dict(data=data)

然后创建一个模板文件 rssfeed.html :

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:py="http://genshi.edgewall.org/">
<channel>
<title>Mental Studio</title>
<link>http://mental.we8log.com</link>
<description>mental studio</description>
<language>zh_CN</language>
<managingEditor>[email protected]</managingEditor>
<copyright>Copyright 2008</copyright>
<generator>TurboGears 1.0.3.2</generator>
<pubDate>2008-09-23</pubDate>
<ttl>60</ttl>
<item py:for="item in data">
<title>${item.title}</title>
<link>${item.url}</link>
<comments>${item.url}</comments>
<description><span style="margin-left: 30px;margin-top: 0px;margin-bottom: 0px;"><b>${item.user}</b> ${item.created} </span>
<p style="margin-left: 30px;margin-top: 2px;margin-bottom: 0px;font-style: italic;">${item.content}</p> </description>
<guid>${item.url}</guid>
<pubDate>${item.created}</pubDate>
</item>
</channel>
</rss>

关键的就是两点:一个是expose的参数,必须指定为输出XML及所用的编码方式;另一个是模板文件要是一个XML的模板,而不是继承来的HTML模板。

三、将HTML数据原样输出(不渲染):

因 为expose会把返回值dict中所有字符串类型的值都作一次渲染——比如把"<"、">"转成"&lt;", "&gt;",这样的话如果想在最终页面里显示插入的HTML内容就不行了,在某些应用中就会有很大的局限。还好Genshi有提供相应的解决方 案。在Q&A里提供了三种解决方案,但是都说得不太清楚,可能是他们觉得这太简单了——当然,我试了其中一个方法,的确非常简单:

    @expose(template="myproj.templates.article")
def showarticle(self,id=None,**kw):
c=self.getArticleContent(id)
cm=Markup(c)
return dict(c=cm)

重点就是那个Markup(),用于将字符串转为Markup对象,这样就能绕过Genshi的render。模板那边则不需要任何改变,同样是用标准的输出方式:

<div id="ArticleContent" py:content="c" />

就这么简单。