<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[limodou的学习生活]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[Python, open source, ...]]></description>
<link>http://hi.baidu.com/limodou</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[uliweb.com.cn]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/a68fb838e98dddc8d46225ed.html]]></link>
        <description><![CDATA[
		
		<span class="Apple-style-span" style="word-spacing: 0px; font: medium YaHei Consolas Hybrid; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px">
<div style="font-weight: normal; font-size: 14px; line-height: normal; font-style: normal; background-color: rgb(255,255,255); background-origin: initial; background-clip: initial">
<p><span style="border-collapse: collapse" mce_style="border-collapse: collapse;">感谢张教主的帮助，不过现在还有一点点小问题，因为有些包还没装上。不过首页已经可以访问了。uliweb已经在张教主的stdyun上部署成功了。几点事项：<span class="Apple-converted-space"> </span><br>
<br>
域名（我去的9host.cn申请的，.<span class="Apple-converted-space"> </span>com.cn<span class="Apple-converted-space"> </span>只要3块钱，续费要50元）<span class="Apple-converted-space"> </span><br>
有了域名要设置对应的IP（IP为：119.88.56.193），具体见张教主的说明(<span class="Apple-style-span" style="font-size: small; border-collapse: separate">同时要注意修改9host的DNS时要使用IE浏览器。<span> <span class="Apple-style-span" style="font-size: 14px; border-collapse: collapse">) &nbsp;&nbsp;</span></span></span></span></p>
<p><span style="border-collapse: collapse" mce_style="border-collapse: collapse;"><a style="color: rgb(119,153,187)" target="_blank" mce_style="color: #7799bb;" mce_href="http://groups.google.com/group/python-cn/browse_thread/thread/3b00351b97b6690a" href="http://groups.google.com/group/python-cn/browse_thread/thread/3b00351b97b6690a#">http://groups.google.com/group/python-cn/browse_thread/thread/3b00351b97b6690a#<span class="Apple-converted-space"> </span></a><br>
然后runcgi.py需要将后缀改为.fcgi。 不过这个我要再更新一下uliweb。<span class="Apple-converted-space"> </span><br>
<br>
回头我会写一个更详细的uliweb在stdyun上的部署说明。</span></p>
<p>声明，<font color="#ff0000">因为我使用的是免费试用，因此可能用的时间不会太长</font>。</p>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/a68fb838e98dddc8d46225ed.html#comment">查看评论</a>]]></description>
        <pubDate>2009-11-05  12:52</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/a68fb838e98dddc8d46225ed.html</guid>
</item>

<item>
        <title><![CDATA[Uliweb之Cache]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/294d09fa7030b69d59ee90dd.html]]></link>
        <description><![CDATA[
		
		<span class="Apple-style-span" style="background-color: transparent; border-collapse: separate; color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">
<div style="font-size: 14px; line-height: normal; font-style: normal; font-weight: normal; background-color: rgb(255, 255, 255);">
<p>在经过对beaker中的session替换之后，我终于又把cache给替换掉了。完全是自个儿重写。一方面它可以象一个dict一样工作，同时可以通过put, get来调用。使用这两个函数的好处就是可以有更多的参数。目前这个类在uliweb/lib/weto/cache.py中。</p>
<p>创建cache</p>
<p>import weto.cache</p>
<p>cache = weto.cache.Cache()</p>
<p>这样可以创建一个cache。因为没有指定Cache类的初始化参数，因此会自动以file格式创建cache。如果需要指定其它的格式和参数，可以设置：</p>
<p>storage_type, options, expiry_time</p>
<p>这三个参数。storage是类型，目前只支持'file', 'dbm', 'database'，分别对应三种不同的存储类型。</p>
<p>options则根据不同的类型有所区别，比如'file'类型需要传入'data_dir'，用以指定cache保存的路径。而'database'则需要指明要使用的表名和数据库连接的一些信息。</p>
<p>expiry_time是指定缺省的超时时间。这是当你在put时没有指定超时时间时使用的，在调用put时可以单独设定。</p>
<p>cache.get(key)</p>
<p>这样的调用，如果key不存在，或超时则会引发一个异常抛出CacheKeyException异常。</p>
<p>如果不想引发异常，则可以：</p>
<p>cache.get(key, default)</p>
<p>其中default不能为None，这样当key不存在，则不会引发异常，返回default值。如果为None，则同get(key)的效果。</p>
<p>cache.put(key, value, expire=None)</p>
<p>这样可以设置一个cache。如果expire没有传入则使用缺省的超时时间。时间以秒为单位。</p>
<p>同时为了方便函数的封装，还提供了</p>
<p>cache.cache(key=None, expire=None)</p>
<p>这个decorator。例如：</p>
<p>@cache.cache(expire=15)<span class="Apple-converted-space">&#160;</span><br>
def f(*args, **kwargs):</p>
<p>或</p>
<p>@cache.cache(key, expire=15)<span class="Apple-converted-space">&#160;</span><br>
def f(*args, **kwargs):</p>
<p>这两种都是可以的，区别在于前一个没有key参数，那它将根据函数名和参数来生成一个key，而后面则是由用户主动指定了一个key。</p>
<p>在进行上进的改造之后，原来的beaker就删除了，这样uliweb中不再使用beaker了。同时对原uliweb.contrib.cache进行了修改，去掉了middle_cache.py，而采用让用户自行调用的机制。同时为了同app的配置功能相结合和方便用户使用，在uliweb/utils/cache.py中编写了一个get_cache()的函数，同时对Cache类的增加了page方法。</p>
<p>get_cache()可以自动从settings中找到相应的配置。目前主通过两个secion来控制的：</p>
<p>[CACHE]和[CACHE_STORAGE]，前者用来控制cache的类型和超时时间。后者是用来针对每一种类型来设置与存储相关的配置信息。在调用get_cache()时，你还可以传入一些参数，它的原型是：</p>
<p>def get_cache(cache_setting_name='CACHE', cache_storage_setting_name='CACHE_STORAGE'):</p>
<p>即可以指明使用其它的配置名，这样就可以在你的settings.ini中存放不同的cache的配置，通过get_cache来使用不同的cache机制。</p>
<p>为什么要对Cache进行扩展，Cache.cache原来是针对函数本身和它的参数，但是这样对于view有一点问题。有些view可能通过QUERY_STRING来处理不同的传入参数，因此在url上它们不同，但是在view函数上是完全一样，因此这种只根据函数本身和参数是有问题的。因此扩展的page这个decorator使用了request.url值，它是一个完整的访问路径，包括了QUERY_STRING信息。因此为了生成静态cache，可以使用改造后的Cache类。当你调用get_cache()时返回的cache对象已经是使用了这个新的Cache类了。</p>
<p>所以为了方便和更适合在Uliweb环境下使用，可以使用uliweb.utils.cache的get_cache()函数。例如：</p>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br>  5 <br>  6 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000ff"><strong>from</strong></font> <font color="#000000">uliweb</font><font color="#0000c0">.</font><font color="#000000">utils</font><font color="#0000c0">.</font><font color="#000000">cache</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">get_cache</font><font color="#0000c0">(</font><font color="#0000c0">)</font><br><font color="#000000">cache</font> <font color="#0000c0">=</font> <font color="#000000">get_cache</font><font color="#0000c0">(</font><font color="#0000c0">)</font> <font color="#008000">#使用缺省的settings.ini设置。因此需要加入uliweb.contrib.cache这个app </font><br><font color="#0000c0">@</font><font color="#000000">cache</font><font color="#0000c0">.</font><font color="#000000">cache</font><font color="#0000c0">(</font><font color="#000000">expire</font><font color="#0000c0">=</font><font color="#0080c0">15</font><font color="#0000c0">)</font><br><font color="#0000c0">@</font><font color="#000000">expose</font><font color="#0000c0">(</font><font color="#804000">'/index'</font><font color="#0000c0">)</font><br><font color="#0000ff"><strong>def</strong></font> <font color="#000000">index</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>    <font color="#0000ff"><strong>return</strong></font> <font color="#0000c0">{</font><font color="#0000c0">}</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
<p> </p>
<p>现在我把uliwebproject也添加了cache的支持，不过发现的问题是，不能简单的使用@cache.page()来对view方法进行处理。原因是：</p>
<p>在view方法中有对cookie的处理，采用cache的方式会屏蔽掉这块处理</p>
<p>因此在uliwebproject中并不是使用的decorator的方式，而是在view中对可以cache化的部分进行了手工处理，如：</p>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br>  5 <br>  6 <br>  7 <br>  8 <br>  9 <br> 10 <br> 11 <br> 12 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#000000">cache</font> <font color="#0000c0">=</font> <font color="#000000">get_cache</font><font color="#0000c0">(</font><font color="#0000c0">)</font><br><font color="#0000c0">@</font><font color="#000000">cache</font><font color="#0000c0">.</font><font color="#000000">cache</font><font color="#0000c0">(</font><font color="#000000">_f</font><font color="#0000c0">)</font><br><font color="#0000ff"><strong>def</strong></font> <font color="#000000">f</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>    <font color="#000000">content</font> <font color="#0000c0">=</font> <font color="#000000">file</font><font color="#0000c0">(</font><font color="#000000">_f</font><font color="#0000c0">)</font><font color="#0000c0">.</font><font color="#000000">read</font><font color="#0000c0">(</font><font color="#0000c0">)</font><br>    <font color="#0000ff"><strong>if</strong></font> <font color="#000000">render</font><font color="#0000c0">:</font><br>        <font color="#000000">content</font> <font color="#0000c0">=</font> <font color="#000000">to_html</font><font color="#0000c0">(</font><font color="#000000">template</font><font color="#0000c0">(</font><font color="#000000">content</font><font color="#0000c0">,</font> <font color="#000000">env</font><font color="#0000c0">=</font><font color="#000000">application</font><font color="#0000c0">.</font><font color="#000000">get_view_env</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">)</font><font color="#0000c0">)</font><br>    <font color="#0000ff"><strong>else</strong></font><font color="#0000c0">:</font><br>        <font color="#000000">content</font> <font color="#0000c0">=</font> <font color="#000000">to_html</font><font color="#0000c0">(</font><font color="#000000">content</font><font color="#0000c0">)</font><br>    <font color="#0000ff"><strong>return</strong></font> <font color="#000000">application</font><font color="#0000c0">.</font><font color="#000000">template</font><font color="#0000c0">(</font><font color="#804000">'show_document.html'</font><font color="#0000c0">,</font> <font color="#000000">locals</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">)</font><br><br><font color="#000000">response</font><font color="#0000c0">.</font><font color="#000000">write</font><font color="#0000c0">(</font><font color="#000000">f</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">)</font><br><font color="#0000ff"><strong>return</strong></font> <font color="#000000">response</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
<div>完全是手工来处理了。</div>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/294d09fa7030b69d59ee90dd.html#comment">查看评论</a>]]></description>
        <pubDate>2009-11-04  12:46</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/294d09fa7030b69d59ee90dd.html</guid>
</item>

<item>
        <title><![CDATA[uliweb性能之优化思考]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/12f14ec2af4a093fe5dd3bb0.html]]></link>
        <description><![CDATA[
		
		<span class="Apple-style-span" style="word-spacing: 0px; font: medium  YaHei Consolas Hybrid ; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px">
<div style="font-weight: normal; font-size: 14px; line-height: normal; font-style: normal;  background-color: rgb(255,255,255); background-origin: initial; background-clip: initial">
<p>性能与功能的确有些矛盾。因为开发uliweb更多是从功能上考虑，因此在性能上我一直没有太仔细测试和分析过。最近找了一个主机部署了一下，别人告诉我刷新一下CPU占用很高，于是我想有机会的确还是要好好搞一下。于是加了一些跟踪，发现了一些问题：</p>
<p>1. get_apps() 的问题</p>
<p>因为uliweb是采用app方式来组织，而且app是允许使用python的包形式。在启动时，为了查找app下的settings.ini和config.ini等信息，使用的是pkgresource的resource_filename，它是要导入才可以的。但是一个导入可能会使得加载变慢。这块的确有些问题。为了查找包的目录，因此要导入，但是后面的处理未必会使用这个包，显得有些浪费。因此我修改了这块处理。如果包是由a.b.c这样形式构成的，我会只导入a，后面两个直接根据a的目录生成一个路径。这样只要保证a的__init__.py中没有太多的耗时的代码就可以了。这样优化后减少了一些时间。</p>
<p>2. pytz的问题</p>
<p>因为uliweb的ORM会处理时区的问题，而且我写了一个utils/date.py模块专门来处理时区转换。因此在启动时，为了省事，我自动导入了date.py模块，它会自动导入pytz模块。但是我发现pytz的导入非常慢。这样造成整个uliweb的启动变慢。因此这块我直接去掉了，让用户自已来处理好了。</p>
<p>3. 可能会引起问题的地方。app的__init__.py文件。因为考虑有些bind的代码会写在__init__.py中，因此在启动app时会自动导入所有app。因此如果有app在这里写了很耗时的代码会影响整个uliweb的启动速度。也许你会认为不好，不过uliweb已经提供了许多静态化的方法，如：bind和expose可以静态化，即在settings.ini中进行配置，这样__init__.py中可以是空的。</p>
<p>这里的问题主要是由于方便性考虑产生的：采用自动化的方式，减少用户的导入或初始化的工作，结果使得处理范围扩大化，影响启动效率。</p>
<p>注意我说的主要是启动时的效率，一旦启动不退出，效率要好一些。</p>
<p>因此uliweb如果每次都是重新启动必然会造成性能下降，比较好的方式还是驻留式，不要每次启动。象mod_wsgi, fastcgi应该是可以支持的。是不是自带一个web server采用反向代理会更好呢？象java一样。</p>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/12f14ec2af4a093fe5dd3bb0.html#comment">查看评论</a>]]></description>
        <pubDate>2009-11-02  22:16</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/12f14ec2af4a093fe5dd3bb0.html</guid>
</item>

<item>
        <title><![CDATA[新的uliwiki项目]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/6085b99992092e026e068cd0.html]]></link>
        <description><![CDATA[
		
		<span style="background-color: transparent; border-collapse: separate; color: rgb(0, 0, 0);  font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;" class="Apple-style-span">
<div style=" font-size: 14px; line-height: normal; font-style: normal; font-weight: normal; background-color: rgb(255, 255, 255);">
<p>今天开发了一个新的uliwiki的项目,不错是今天,我是照着<span class="Apple-converted-space">&#160;</span><span style="background-color: rgb(255, 255, 255);" mce_style="background-color: #ffffff; "><a target="_blank" mce_href="http://code.google.com/p/django-wikiapp/" href="http://code.google.com/p/django-wikiapp/">http://code.google.com/p/django-wikiapp/<span class="Apple-converted-space">&#160;</span></a>这个项目来做的,不过象界面,象处理许多都是重写的.因为原来的项目功能挺多,我目前还实现不了,比如:comment, tagging, notification, feed等.目前只是实现了一个基本的wiki的功能,用户认证还没有.但是wiki的功能基本上都全了:</span></p>
<p><span style="background-color: rgb(255, 255, 255);" mce_style="background-color: #ffffff; ">比如生成WikiWord链接,同时支持象[wiki:name message]的wikiword方式.</span></p>
<p>使用reStructuredText格式(目前只支持这一种)</p>
<p>编辑,删除,版本管理,恢复旧版本,查看旧版本.</p>
<p>其中版本管理我做得比较简单,我是每次保留全部内容,而不是增量内容,主要是为了方便生成版本差异.而django-wikiapp是保存的增量内容,因此处理上要复杂一些.</p>
<p>同时通过研究django-wikiapp发现了　<span class="Apple-converted-space">&#160;</span><span style="background-color: rgb(255, 255, 255);" mce_style="background-color: #ffffff; "><a target="_blank" mce_href="http://code.google.com/p/google-diff-match-patch/" href="http://code.google.com/p/google-diff-match-patch/">http://code.google.com/p/google-diff-match-patch/<span class="Apple-converted-space">&#160;</span></a>这个好东西,可以用来生成比较后的结果,并且还可以生成patch.</span></p>
<p>下面上几张图,看下效果:</p>
<p style="text-align: center;" mce_style="text-align:center;"><img style="border-width: 0px; width: 590px;" mce_src="http://photo.zeuux.com/photo/gallery/3910/original/" src="http://photo.zeuux.com/photo/gallery/3910/original/"></p>
<p style="text-align: center;" mce_style="text-align:center;">这是进入的首页面.</p>
<p style="text-align: center;" mce_style="text-align:center;"><img style="border-width: 0px; width: 590px;" mce_src="http://photo.zeuux.com/photo/gallery/3911/original/" src="http://photo.zeuux.com/photo/gallery/3911/original/"></p>
<p style="text-align: center;" mce_style="text-align:center;">这是某个页面的编辑页面</p>
<p style="text-align: center;" mce_style="text-align:center;"><img style="border-width: 0px;" mce_src="http://photo.zeuux.com/photo/gallery/3912/original/" src="http://photo.zeuux.com/photo/gallery/3912/original/"></p>
<p style="text-align: center;" mce_style="text-align:center;">这是版本信息,先选中不同的版本,然后点上面的Compare按钮可以显示下面的比较结果.</p>
<p style="text-align: center;" mce_style="text-align:center;"><img style="border-width: 0px; width: 590px;" mce_src="http://photo.zeuux.com/photo/gallery/3913/original/" src="http://photo.zeuux.com/photo/gallery/3913/original/"></p>
<p style="text-align: center;" mce_style="text-align:center;">这是使用了google-diff-match-patch显示的结果,还不错.</p>
<p style="text-align: left;" mce_style="text-align: left;">现在uliwiki的地址在　<span class="Apple-converted-space">&#160;</span><span style="background-color: rgb(255, 255, 255);" mce_style="background-color: #ffffff;"><a target="_blank" mce_href="http://code.google.com/p/uliwiki/" href="http://code.google.com/p/uliwiki/">http://code.google.com/p/uliwiki/<span class="Apple-converted-space">&#160;</span></a>&#160;有兴趣可以试试和完善它.</span></p>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/6085b99992092e026e068cd0.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-18  21:32</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/6085b99992092e026e068cd0.html</guid>
</item>

<item>
        <title><![CDATA[对《I have a dream》的回复]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/9079bd3e7f3753f0828b13ca.html]]></link>
        <description><![CDATA[
		
		<span style="background-color: transparent; border-collapse: separate; color: rgb(0, 0, 0);  font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;" class="Apple-style-span"><span style=" font-size: 14px; line-height: 21px; text-align: left;" class="Apple-style-span">
<p style="margin: 1em 0px 0.5em; padding: 0px;">原文：&#160;<a style="text-decoration: none; color: rgb(0, 107, 173);" href="http://j-lite.net/blog/2009/10/17/i-have-a-dream">http://j-lite.net/blog/2009/10/17/i-have-a-dream</a></p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">以下是我的回复：</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">我也不是为了争uliweb要比django强大，我也说了uliweb有自已的优势，而且我认为比django强的，但django也有它的优势。而且我也在邮件列表中多次声明，每个框架代表一种哲学，不同的哲学引来不同的用户，所以我离开django也可以说是我的哲学与django的哲学区别越来越多造成的。</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">至于造轮的问题，因此我还是建议你有时间多了解一下uliweb。在今年9.5日的大会上我列举了自已创建的轮子的例子，比如：</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">整个核心的处理完全是自已写的，它是一个框架的灵魂，负责整个框架的启动，组件管理(app管理)，配置管理，request和response处理，middleware的处理，这是每个框架不同于其它框架的核心，是无法复制的。如果只是简单的复制，那么这个框架存在的意义就没有了。其中整个app的详细支持是借鉴了django的思路，但是由我完善的。还有象view的处理，借鉴了web2py的思路，但是自已实现的。详细代码可以见uliweb.core.SimpleFrame.py.</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">还有许多的模块是我自已写的：</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">1. web2py的模板，已经被我改造增加了象编译文件目录支持，自定义tag支持，block的支持，这些都是原模板没有了，已经是uliweb化的组件了。<br>
2.dispatch模块，完全是自已写的，实现类似于django signal的功能。但是整个实现是从ulipad发展来的，没有照搬任何人的东西。<br>
3.i18n也是自已写的，是从ulipad发展来的。<br>
4.weto是在我发现beaker这个session库有问题之后重写的，完全是uliweb的东西。<br>
5.contrib下的所有组件都是我自已写的。<br>
6.pyini完全是自已构思创造出来的，用于处理uliweb的配置文件。<br>
7.orm这块是从头一点点构建的，也是一个框架很重要的部分。<br>
8.form库也是自已一点点写的。<br>
9.url映射的处理机制是使用了werkzeug的route为基础实现的，但是只是使用了它的基本功能，主要功能是uliweb实现的。</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">一个框架主要完成的功能其实不外乎：url处理，request, response，view，orm，组件管理，配置管理，提供一些实用的扩展。因此，你可以看到，从架构设计，从组件的实现，许多方面都有uliweb自已的实现，甚至完全是uliweb自已的实现。因此从web2py，从django，从werkzeug，从sqlalchemy更多不是简单的引用，而是思想的借鉴，是更多的封装。</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">所以，许多东西并不是简单了解就好象明白的。这是我想要澄清的地方。别人不认可uliweb没关系，很正常。但是我只是希望，评论一个东西首先要对它多少深入地了解一下，哪怕与作者交流一下也好，而是不看些表面。不仅从合理客观的角度来谈论一件事，更是不会误导别人。所以uliweb绝不是简单地组装出来的一个东西，它有自已特性甚至独一无二的东西。许多人一谈uliweb，就是从重装造轮的角度，但是他们并不了解许多uliweb上的设计的东西，也基本上没有在技术细节上的讨论，谈得很泛泛。这样对谁都不是公平的。</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">你所说的框架其实目前pylons和tg都差不多，而uliweb也是可以，django也是可以，只不过pylons和tg可能从组件上可以直接选择，而uliweb,django是可以自已定制开发，不能直接使用。而且你所说的更接近于某些人更偏重于自已去建，比如这篇文章：</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">http://pythonpaste.org/webob/do-it-yourself.html</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">自已建是没有问题。因此框架更多是给那些不希望，甚至不能够自已来做这件事的人准备的。但是自已建，可能需要了解的东西更多，正如我在构建uliweb过程中，我学到了比以前简单使用框架更多的东西，我甚至做了许多以前不知道自已还可以做的事情。各有各的乐趣。</p>
</span></span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/9079bd3e7f3753f0828b13ca.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-18  10:41</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/9079bd3e7f3753f0828b13ca.html</guid>
</item>

<item>
        <title><![CDATA[关于Webob无法支持flash文件上传问题的记录]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/7a7fb58f3a6dc9e4f01f3681.html]]></link>
        <description><![CDATA[
		
		<em>根据邮件列表中的回复加工</em><br>
<br>
1. 提出问题：<br>
<br>
使用webob在处理通过fancyupload上传的文件，发现会系统挂起，但只要先把request.body读出来就没有问题。因此在uliweb中，将原来使用的webob去除，改成了werkzeug来处理了。<br>
<br>
2. qiangninghong的试验：<br>
<br>
因为limodou反应的这个问题认为是cgi模块有bug导致的，所以很重要。今天晚上稍稍有点时间，写了一个测试程序来验证一下，但是发现似乎没有这样的情况？<br>
<br>
测试代码在这里 http://code.google.com/p/hongqnlib/source/browse/<br>
<br>
就是照着 FancyUpload 的 Attach File demo 页面 ( http://digitarald.de/project/fancyupload/3-0/showcase/attach-a-file/ ) 翻译了一下。运行 server.py 后，访问 http://localhost:5002/ ，上传了几个文件，都没有出现挂住的情况啊？<br>
<br>
难道是我的这个测试有什么问题？请 limodou 帮忙看看。<br>
<br>
3. 我的试验：<br>
<br>
我把你的程序改了一下：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br>  5 <br>  6 <br>  7 <br>  8 <br>  9 <br> 10 <br> 11 <br> 12 <br> 13 <br> 14 <br> 15 <br> 16 <br> 17 <br> 18 <br> 19 <br> 20 <br> 21 <br> 22 <br> 23 <br> 24 <br> 25 <br> 26 <br> 27 <br> 28 <br> 29 <br> 30 <br> 31 <br> 32 <br> 33 <br> 34 <br> 35 <br> 36 <br> 37 <br> 38 <br> 39 <br> 40 <br> 41 <br> 42 <br> 43 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000ff"><strong>import</strong></font> <font color="#000000">os</font><br><font color="#0000ff"><strong>import</strong></font> <font color="#000000">mimetypes</font><br><font color="#0000ff"><strong>import</strong></font> <font color="#000000">time</font><br><font color="#0000ff"><strong>import</strong></font> <font color="#000000">socket</font><br><font color="#0000ff"><strong>from</strong></font> <font color="#000000">hashlib</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">md5</font><br><font color="#0000ff"><strong>import</strong></font> <font color="#000000">simplejson</font> <font color="#0000ff"><strong>as</strong></font> <font color="#000000">json</font><br><font color="#0000ff"><strong>import</strong></font> <font color="#000000">webob</font><font color="#0000c0">,</font> <font color="#000000">webob</font><font color="#0000c0">.</font><font color="#000000">exc</font><br><font color="#0000ff"><strong>from</strong></font> <font color="#000000">paste</font><font color="#0000c0">.</font><font color="#000000">urlparser</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">StaticURLParser</font><br><font color="#0000ff"><strong>from</strong></font> <font color="#000000">paste</font><font color="#0000c0">.</font><font color="#000000">cascade</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">Cascade</font><br><font color="#0000ff"><strong>import</strong></font> <font color="#000000">logging</font><br><font color="#0000ff"><strong>from</strong></font> <font color="#000000">paste</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">fileapp</font><br><br><br><font color="#0000ff"><strong>def</strong></font> <font color="#000000">app</font><font color="#0000c0">(</font><font color="#000000">environ</font><font color="#0000c0">,</font> <font color="#000000">start_response</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>   <font color="#000000">request</font> <font color="#0000c0">=</font> <font color="#000000">webob</font><font color="#0000c0">.</font><font color="#000000">Request</font><font color="#0000c0">(</font><font color="#000000">environ</font><font color="#0000c0">)</font><br>   <font color="#0000ff"><strong>if</strong></font> <font color="#000000">request</font><font color="#0000c0">.</font><font color="#000000">method</font> <font color="#0000c0">==</font> <font color="#804000">'GET'</font><font color="#0000c0">:</font><br>       <font color="#000000">filename</font> <font color="#0000c0">=</font> <font color="#000000">request</font><font color="#0000c0">.</font><font color="#000000">path_info</font><font color="#0000c0">.</font><font color="#000000">lstrip</font><font color="#0000c0">(</font><font color="#804000">'/'</font><font color="#0000c0">)</font><br>       <font color="#000000">response</font> <font color="#0000c0">=</font> <font color="#000000">fileapp</font><font color="#0000c0">.</font><font color="#000000">FileApp</font><font color="#0000c0">(</font><font color="#000000">filename</font><font color="#0000c0">)</font><br>   <font color="#0000ff"><strong>else</strong></font><font color="#0000c0">:</font><br><font color="#008000">#        logging.error( repr(request.body))<br></font>       <font color="#000000">filedata</font> <font color="#0000c0">=</font> <font color="#000000">request</font><font color="#0000c0">.</font><font color="#000000">POST</font><font color="#0000c0">[</font><font color="#804000">'Filedata'</font><font color="#0000c0">]</font><br>       <font color="#000000">r</font> <font color="#0000c0">=</font> <font color="#000000">dict</font><font color="#0000c0">(</font><font color="#000000">status</font><font color="#0000c0">=</font><font color="#804000">'1'</font><font color="#0000c0">,</font> <font color="#000000">name</font><font color="#0000c0">=</font><font color="#000000">filedata</font><font color="#0000c0">.</font><font color="#000000">filename</font><font color="#0000c0">)</font><br>       <font color="#000000">text</font> <font color="#0000c0">=</font> <font color="#000000">filedata</font><font color="#0000c0">.</font><font color="#000000">file</font><font color="#0000c0">.</font><font color="#000000">read</font><font color="#0000c0">(</font><font color="#0000c0">)</font><br>       <font color="#000000">r</font><font color="#0000c0">[</font><font color="#804000">'hash'</font><font color="#0000c0">]</font> <font color="#0000c0">=</font> <font color="#000000">md5</font><font color="#0000c0">(</font><font color="#000000">text</font><font color="#0000c0">)</font><font color="#0000c0">.</font><font color="#000000">hexdigest</font><font color="#0000c0">(</font><font color="#0000c0">)</font><br>       <font color="#0000ff"><strong>if</strong></font> <font color="#000000">request</font><font color="#0000c0">.</font><font color="#000000">params</font><font color="#0000c0">.</font><font color="#000000">get</font><font color="#0000c0">(</font><font color="#804000">'response'</font><font color="#0000c0">)</font> <font color="#0000c0">==</font> <font color="#804000">'xml'</font><font color="#0000c0">:</font><br>           <font color="#000000">response</font> <font color="#0000c0">=</font> <font color="#000000">webob</font><font color="#0000c0">.</font><font color="#000000">Response</font><font color="#0000c0">(</font><font color="#000000">content_type</font><font color="#0000c0">=</font><font color="#804000">'text/xml'</font><font color="#0000c0">)</font><br>           <font color="#0000ff"><strong>print</strong></font> <font color="#0000c0">&gt;&gt;</font><font color="#000000">response</font><font color="#0000c0">.</font><font color="#000000">body_file</font><font color="#0000c0">,</font> <font color="#804000">'&lt;response&gt;'</font><br>           <font color="#0000ff"><strong>for</strong></font> <font color="#000000">k</font><font color="#0000c0">,</font> <font color="#000000">v</font> <font color="#0000ff"><strong>in</strong></font> <font color="#000000">r</font><font color="#0000c0">.</font><font color="#000000">items</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>               <font color="#0000ff"><strong>print</strong></font> <font color="#0000c0">&gt;&gt;</font><font color="#000000">response</font><font color="#0000c0">.</font><font color="#000000">body_file</font><font color="#0000c0">,</font> \<br>                       <font color="#804000">&quot;&lt;%(k)s&gt;&lt;![CDATA[%(v)s]]&gt;&lt;/%(k)s&gt;&quot;</font> <font color="#0000c0">%</font> <font color="#000000">locals</font><font color="#0000c0">(</font><font color="#0000c0">)</font><br>           <font color="#0000ff"><strong>print</strong></font> <font color="#0000c0">&gt;&gt;</font><font color="#000000">response</font><font color="#0000c0">.</font><font color="#000000">body_file</font><font color="#0000c0">,</font> <font color="#804000">'&lt;/response&gt;'</font><br>       <font color="#0000ff"><strong>else</strong></font><font color="#0000c0">:</font><br>           <font color="#000000">response</font> <font color="#0000c0">=</font> <font color="#000000">webob</font><font color="#0000c0">.</font><font color="#000000">Response</font><font color="#0000c0">(</font><font color="#000000">content_type</font><font color="#0000c0">=</font><font color="#804000">'application/json'</font><font color="#0000c0">,</font><br>                                     <font color="#000000">body</font><font color="#0000c0">=</font><font color="#000000">json</font><font color="#0000c0">.</font><font color="#000000">dumps</font><font color="#0000c0">(</font><font color="#000000">r</font><font color="#0000c0">)</font><font color="#0000c0">)</font><br>   <font color="#0000ff"><strong>return</strong></font> <font color="#000000">response</font><font color="#0000c0">(</font><font color="#000000">environ</font><font color="#0000c0">,</font> <font color="#000000">start_response</font><font color="#0000c0">)</font><br><br><font color="#008000">#static_app = StaticURLParser('/static')<br></font><font color="#008000">#app = Cascade([static_app, app], (404, 405))<br></font><br><font color="#0000ff"><strong>if</strong></font> <font color="#000000">__name__</font> <font color="#0000c0">==</font> <font color="#804000">'__main__'</font><font color="#0000c0">:</font><br>   <font color="#0000ff"><strong>from</strong></font> <font color="#000000">wsgiref</font><font color="#0000c0">.</font><font color="#000000">simple_server</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">make_server</font><br>   <font color="#000000">server</font> <font color="#0000c0">=</font> <font color="#000000">make_server</font><font color="#0000c0">(</font><font color="#804000">'localhost'</font><font color="#0000c0">,</font> <font color="#0080c0">5002</font><font color="#0000c0">,</font> <font color="#000000">app</font><font color="#0000c0">)</font><br>   <font color="#000000">server</font><font color="#0000c0">.</font><font color="#000000">serve_forever</font><font color="#0000c0">(</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
分析如下：<br>
<br>
1. 使用你的程序的确没有问题，使用我改的程序就有问题<br>
2. 两个差别在于你在调用处理前使用了一个StaticURLParser，而我改后的程序是不使用它，在app中自已处理。这样的目的并不是使用StaticURLParser不行，而是这样的做法其实是在app处理前多了一层处理，那么这层处理会影响后面的处理，掩盖问题的发生。<br>
3. 在我的例子中，只要把#&#160;&#160;&#160;&#160;&#160;&#160;&#160; logging.error( repr(request.body))这行的注释去了，程序就正常。<br>
4. 原因就是，只要你想办法在执行request.POST['Filedata']之前执行了象request.body之类的代码，这样会引起对body的整个读取，这时读取是按Content-Length来处理的，并且会放在缓冲区中，因此后续的处理就是从这个缓冲区来的了，因此缓冲区最后有没有回车换行是没有关系的。而使用flash控件上传文件，文件体示例如下：<br>
<br>
ERROR:root:'------------ei4GI3ei4Ef1Ef1GI3ei4Ij5GI3GI3\r\nContent-Disposition:<br>
form-data; name=&quot;Filename&quot;\r\n\r\na.c\r\n------------ei4GI3ei4Ef1Ef1GI3ei4Ij5GI3G<br>
I3\r\nContent-Disposition: form-data; name=&quot;Filedata&quot;;<br>
filename=&quot;a.c&quot;\r\nContent-Type:<br>
application/octet-stream\r\n\r\n#include<br>
&lt;stdio.h&gt;\r\n\r\n------------ei4<br>
GI3ei4Ef1Ef1GI3ei4Ij5GI3GI3\r\nContent-Disposition: form-data;<br>
name=&quot;Upload&quot;\r\n\r\nSubmit<br>
Query\r\n------------ei4GI3ei4Ef1Ef1GI3ei4Ij5GI3GI3--'<br>
<br>
可以看到，最后是没有\r\n的。这不是浏览器的问题，是flash组件本身的问题，相关的flash的类本身的问题。但其实也不算一个问题，因为cgi的处理是基于multipart的boundary需要以\r\n结束这个假设，但这种假设在某些情况下有问题。相应的cgi的代码如下（从cgi.py中找到的703行）：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br>  5 <br>  6 <br>  7 <br>  8 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000ff"><strong>def</strong></font> <font color="#000000">read_lines_to_eof</font><font color="#0000c0">(</font><font color="#000000">self</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>   <font color="#804000">&quot;&quot;&quot;Internal: read lines until EOF.&quot;&quot;&quot;</font><br>   <font color="#0000ff"><strong>while</strong></font> <font color="#0080c0">1</font><font color="#0000c0">:</font><br>       <font color="#000000">line</font> <font color="#0000c0">=</font> <font color="#000000">self</font><font color="#0000c0">.</font><font color="#000000">fp</font><font color="#0000c0">.</font><font color="#000000">readline</font><font color="#0000c0">(</font><font color="#0080c0">1</font><font color="#0000c0">&lt;&lt;</font><font color="#0080c0">16</font><font color="#0000c0">)</font><br>       <font color="#0000ff"><strong>if</strong></font> <font color="#0000ff"><strong>not</strong></font> <font color="#000000">line</font><font color="#0000c0">:</font><br>           <font color="#000000">self</font><font color="#0000c0">.</font><font color="#000000">done</font> <font color="#0000c0">=</font> <font color="#0000c0">-</font><font color="#0080c0">1</font><br>           <font color="#0000ff"><strong>break</strong></font><br>       <font color="#000000">self</font><font color="#0000c0">.</font><font color="#000000">__write</font><font color="#0000c0">(</font><font color="#000000">line</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
就是这个readline造成的，如果没有\r\n它根本不会返回。<br>
<br>
因此前面的问题就是，如果不先执行request.body，则后面的request.POST['Filedata']会从流中进行读取，而不是缓冲区中，但flash正好又不返回\r\n，因此server在使用readline就停处了，造成挂起，进而引发浏览器的flash控件的超时。<br>
<br>
而你的例子使用了StaticURLParser，可能会进行request.body的读取，所以掩盖了这个问题。当然它到底怎么做的，我没有继续深究。因此我改了你的程序，就是为了不让其它的因素干扰，问题就暴露出来了。<br> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/7a7fb58f3a6dc9e4f01f3681.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-17  11:09</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/7a7fb58f3a6dc9e4f01f3681.html</guid>
</item>

<item>
        <title><![CDATA[Uliweb中ORM的新变化]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/d5c135a89aa3d4bbca130c4c.html]]></link>
        <description><![CDATA[
		
		最近一段时间一直在忙着ORM的优化，其中有几点：<br>
<br>
1.增加__table_args__的配置。它和__tablename__一样是定义在Model类中的，可以用来增加在执行Table时添加新的一些参数，如果你使用mysql，可以如下定义：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000ff"><strong>class</strong></font> <font color="#000000">Todo</font><font color="#0000c0">(</font><font color="#000000">Model</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>    <font color="#000000">__table_args__</font> <font color="#0000c0">=</font> <font color="#000000">dict</font><font color="#0000c0">(</font> <font color="#000000">mysql_engine</font><font color="#0000c0">=</font><font color="#804000">'InnoDB'</font><font color="#0000c0">,</font> <font color="#000000">mysql_charset</font><font color="#0000c0">=</font><font color="#804000">'utf8'</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
这样将在建表时，向Table中添加这样的信息。上面的代码将以InnoDB和utf8编码来创建todo表。<br>
<br>
2.增加OnInit类方法的调用。这个方法是交给用户来定义的，可以用来执行在执行完Table之后的一些初始化操作，它将在建表之前。比如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000c0">@</font><font color="#000000">classmethod</font><br><font color="#0000ff"><strong>def</strong></font> <font color="#000000">OnInit</font><font color="#0000c0">(</font><font color="#000000">cls</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>    <font color="#000000">Index</font><font color="#0000c0">(</font><font color="#804000">'my_indx'</font><font color="#0000c0">,</font> <font color="#000000">cls</font><font color="#0000c0">.</font><font color="#000000">c</font><font color="#0000c0">.</font><font color="#000000">title</font><font color="#0000c0">,</font> <font color="#000000">cls</font><font color="#0000c0">.</font><font color="#000000">c</font><font color="#0000c0">.</font><font color="#000000">owner</font><font color="#0000c0">,</font> <font color="#000000">unique</font><font color="#0000c0">=</font><font color="#000000">True</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
这样将创建以title, owner的索引，并且索引不允许重复。目前只支持索引的创建。对于简单的索引，是可以在定义Field时直接设置index=True来创建的，并不需要这种方式。这种方式可以认为就是为了创建多个字段的联合索引。<br>
<br>
3.考虑缺省order_by的实现。但是想用户完全可以在Model中定义相应的方法来实现，类似于django的Manager的东西，比如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000ff"><strong>class</strong></font> <font color="#000000">Todo</font><font color="#0000c0">(</font><font color="#000000">Model</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>    <font color="#0000c0">@</font><font color="#000000">classmethod</font><br>    <font color="#0000ff"><strong>def</strong></font> <font color="#000000">files</font><font color="#0000c0">(</font><font color="#000000">cls</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>        <font color="#0000ff"><strong>return</strong></font> <font color="#000000">cls</font><font color="#0000c0">.</font><font color="#000000">all</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">.</font><font color="#000000">order_by</font><font color="#0000c0">(</font><font color="#000000">cls</font><font color="#0000c0">.</font><font color="#000000">c</font><font color="#0000c0">.</font><font color="#000000">title</font><font color="#0000c0">.</font><font color="#000000">desc</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
然后在使用时可以通过Todo.files()来返回按title降序排列的结果。所以使用这种方法倒是不一定要支持缺省order_by的配置项。不过有这个配置项的好处就是当需要实现通用的查询时，它可以自动生效。不过也可以考虑把结果集当成一个参数传给配置功能，总之还是有方法。<br>
<br>
4.最重要的一个特性。增加表的注册，并且注册的表不一定是一个Model，而是一个模块名的形式，如以下两种都是正确的注册方式：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#000000">set_model</font><font color="#0000c0">(</font><font color="#000000">Model</font><font color="#0000c0">,</font> <font color="#000000">tablename</font><font color="#0000c0">=</font><font color="#804000">'user'</font><font color="#0000c0">)</font><br><font color="#000000">set_model</font><font color="#0000c0">(</font><font color="#804000">'uliweb.contrib.auth.models.User'</font><font color="#0000c0">,</font> <font color="#000000">tablename</font><font color="#0000c0">=</font><font color="#804000">'user'</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
这样注册之后，你就可以通过使用真正的表名来得到对应的Model类对象了。通过：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#000000">User</font> <font color="#0000c0">=</font> <font color="#000000">get_model</font><font color="#0000c0">(</font><font color="#804000">'user'</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
这种方式首先可以使用在关系的定义中，如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#000000">Reference</font><font color="#0000c0">(</font><font color="#804000">'user'</font><font color="#0000c0">)</font><br><font color="#000000">ManyToMany</font><font color="#0000c0">(</font><font color="#804000">'user'</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
对于关系定义，它可以根据表名自动导入对应的Model。而对于在程序中想直接使用某个Model，则可以通过get_model()来获取。<br>
<br>
但是这种get_model()的方式要依赖于set_model()的注册过程。注册有几种方式：<br>
<br>
1. 在导入Model文件时，随着Model的class的创建自动会调用set_model()来注册，因此只要正常导入相应的模块，就可以使用get_model()方法了。这种情况下，对通常的开发没有什么影响，用户甚至不必使用这种方式。<br>
<br>
2. 由框架来注入。也就是uliweb来实现。这种方式首先要求将Model信息写入到settings.ini中，比如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top"> </td>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000c0">[</font><font color="#000000">MODELS</font><font color="#0000c0">]</font><br><font color="#000000">user</font> <font color="#0000c0">=</font> <font color="#804000">'uliweb.contrib.auth.models.User'</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
这样当uliweb在启动时可以自动采集注册信息。然后在orm这个app的__init__.py中执行真正的注册工作，通过调用set_model()方法。这时，注册的就不是Model了，而是字符串形式的信息。<br>
<br>
然后在某个地方，如views.py中使用get_model()或导入models.py时，就可以自动生效了。<br>
<br>
你可能会问，这有什么用呢？一般不都是直接导入来使用吗？完全够用了。<br>
<br>
的确，一般的程序的确是根本用不上。但是Uliweb是一个框架，它要考虑代码的复用和替换的问题。考虑一下，在你的models.py可能需要对User表进行处理，那么你会去导入它。但是有可能这个User表不适合你的应用了，你怎么办？并且这个User表不是你自已写的，而是框架或别人提供的，别人可能还要依赖于这个表。因此简单的直接修改并不一定是好办法，因为它可能不受你的控制。重新写一个可能是好办法，但是因为直接导入的原因，比如你是通过：<br>
<pre><font face="Lucida,Courier New"><font color="#0000ff"><strong>from</strong></font> <font color="#000000">uliweb</font><font color="#0000c0">.</font><font color="#000000">contrib</font><font color="#0000c0">.</font><font color="#000000">auth</font><font color="#0000c0">.</font><font color="#000000">models</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">User</font></font></pre>
这可是直接hard code了，所以重新写必然还要修改导入的代码。那么要解决这个问题，可以采用的一种办法就是将外部依赖的内容配置化，和java中的注入依赖有些象。也就是我在定义自已的东西时，可能需要外部的东西，那么我并不直接导入，而是通过一种获取的方式来得到。这样工并不需要知道外部的组件的实际位置，这件事由框架来完成。因此uliweb现在实现的get_model就是为了实现这一配置化而设计的。<br>
<br>
其实现在，象bind，expose都已经是可以配置化的了，都可以放在settings.ini中。如果完全配置化，将可以减少启动时的导入处理，并且替换会很容易。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/d5c135a89aa3d4bbca130c4c.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-15  21:38</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/d5c135a89aa3d4bbca130c4c.html</guid>
</item>

<item>
        <title><![CDATA[pyini.py的新功能]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/88483801857fe1047bec2c88.html]]></link>
        <description><![CDATA[
		
		<span style="background-color: transparent; border-collapse: separate; color: rgb(0, 0, 0);  font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;" class="Apple-style-span">
<div style="margin: 8px; color: rgb(0, 0, 0);  font-size: 12px; background-color: rgb(255, 255, 255);">
<div>
<p style="margin: 0px; padding: 0px;">pyini.py是处理Uliweb的settings.ini的模块，今天向它添加了三个新的方法：set_var, get_var, del_var，它们的特点集中在第一个参数，它可以是'/'分开的字符串，如：'DEFAULT/flag'，它相当于：</p>
<p style="margin: 0px; padding: 0px;">s = ini.add('DEFAULT')&#160;<br>
s['flag'] = True&#160;</p>
<p style="margin: 0px; padding: 0px;">注意，它只支持一层的'/'切分，如：'DEFAULT/flag/name'相当于 'DEFAULT'和'flag/name'。</p>
</div>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/88483801857fe1047bec2c88.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-15  20:18</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/88483801857fe1047bec2c88.html</guid>
</item>

<item>
        <title><![CDATA[关于《谈谈我对Uliweb的看法》的回复]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/855530ad579921034a36d646.html]]></link>
        <description><![CDATA[
		
		<span style="background-color: transparent; border-collapse: separate; color: rgb(0, 0, 0);  font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;" class="Apple-style-span">
<div style=" font-size: 14px; line-height: normal; font-style: normal; font-weight: normal; background-color: rgb(255, 255, 255);">
<p>原文：&#160;<span class="Apple-converted-space">&#160;</span><span style="background-color: rgb(255, 255, 255);" mce_style="background-color: #ffffff;"><a target="_blank" mce_href="http://j-lite.net/blog/2009/09/28/lets-talk-about-uliweb" href="http://j-lite.net/blog/2009/09/28/lets-talk-about-uliweb">http://j-lite.net/blog/2009/09/28/lets-talk-about-uliweb</a></span></p>
<p>回复如下：</p>
<p><span style=" font-size: 15px; line-height: 21px;" mce_style=" font-size: 15px; line-height: 21px;">首先感谢对Uliweb的批评。 以下要澄清：</span></p>
<p><span style=" font-size: 15px; line-height: 21px;" mce_style=" font-size: 15px; line-height: 21px;">1. 其实所有的框架都是大杂烩，django也不利外。而且别人做好的东西，如果没有什么问题，拿过来用当然就可以了。特别象是框架，它更多的是提供管理模式和一些工具，本身就是个大杂烩。</span></p>
<p><span style=" font-size: 15px; line-height: 21px;" mce_style=" font-size: 15px; line-height: 21px;">2. 大一统是不可能的，正如世界上有那么多可以统一的东西为什么没有统一，如：语言，操作系统，数据库？因为多样性才是这个世界的特点。更因为人们总有不同的思念和需求。</span></p>
<p><span style=" font-size: 15px; line-height: 21px;" mce_style=" font-size: 15px; line-height: 21px;">3. 为什么不向django和web2py做贡献？贡献我的确做过，如果你去查django和web2py相关的内容，应该还有我的名字。但是有些东西是不可调合的，比如对设计的一些看法，对一些组件的使用，这些东西我建议过，他们并不接受。所以只有以自已的方式来构造。</span></p>
<p><span style=" font-size: 15px; line-height: 21px;" mce_style=" font-size: 15px; line-height: 21px;">重新构造也是一个很痛苦的过程，但是可以让造出来的东西完全按自已的意愿发展，也是一种不错的选择。更有一些人不建议使用框架，而是使用组件，为什么，就是不想被框架所束缚。</span></p>
<p><span style=" font-size: 15px; line-height: 21px;" mce_style=" font-size: 15px; line-height: 21px;">而你所说的插件系统，就是uliweb实现的一个目标。uliweb的app的功能要比django还要彻底。如果有兴趣欢迎与我交流。</span></p>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/855530ad579921034a36d646.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-15  07:45</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/855530ad579921034a36d646.html</guid>
</item>

<item>
        <title><![CDATA[Uliweb被Softpedia Team收录]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/f4bfd31b0e794fdfac6e755c.html]]></link>
        <description><![CDATA[
		
		<span style="background-color: transparent; border-collapse: separate; color: rgb(0, 0, 0);  font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;" class="Apple-style-span">
<div style="margin: 8px; color: rgb(0, 0, 0);  font-size: 12px; background-color: rgb(255, 255, 255);">
<p style="margin: 0px; padding: 0px;">原文如下：</p>
<p style="margin: 0px; padding: 0px;"> </p>
<blockquote>
<p style="margin: 0px; padding: 0px;">Congratulations,<br>
<br>
Uliweb, one of your products, has been added to Softpedia's database of<br>
software programs for Linux. It is featured with a description text,<br>
screenshots, download links and technical details on this page:<br>
<a target="_blank" mce_href="http://linux.softpedia.com/get/Internet/HTTP-WWW-/Uliweb-51417.shtml" href="http://linux.softpedia.com/get/Internet/HTTP-WWW-/Uliweb-51417.shtml">http://linux.softpedia.com/get/Internet/HTTP-WWW-/Uliweb-51417.shtml</a><br>
<br>
The description text was created by our editors, using sources such as<br>
text from your product's homepage, information from its help system, the<br>
PAD file (if available) and the editor's own opinions on the program<br>
itself.<br>
<br>
<br>
<br>
If you feel that having your product listed on Softpedia is not a benefit<br>
for you or simply need something changed or updated, please contact us via<br>
email at&#160;<a mce_href="mailto:webmaster@softpedia.com" href="mailto:webmaster@softpedia.com">webmaster@softpedia.com</a>&#160;and we will work with you to fix any<br>
problem you may have found with the product's listing.<br>
<br>
--<br>
Sincerely,<br>
The Softpedia Team</p>
<p style="margin: 0px; padding: 0px;"> </p>
</blockquote>
<p style="margin: 0px; padding: 0px;">不知道算不算好事。不过Uliweb还有许多需要完善的地方，我才把0.0.1a2发布上去，过会就收到了。</p>
</div>
</span> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/f4bfd31b0e794fdfac6e755c.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-13  22:21</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/f4bfd31b0e794fdfac6e755c.html</guid>
</item>


</channel>
</rss>