2006年07月30日

今天在新浪的会议室举行了第九次会课。到会有八人。会议有两个议题:

  • Leo的使用介绍--zoom.quiet
  • LightTracker开始介绍--alax.dong

Leo是Zoom.quiet日常必不可少的东西,安装很早,使用基本上从2005年下半年开始。Leo是一款称为“文学编程”方式的编辑器。可以简单地说:面向结构,模板化编程。如何理解呢?对于一个程序,除了代码还有象注释,说明,算法等逻辑单位,在一般的编辑器是面向文本或代码的,你无法有直观的方式看到文档或项目的逻辑结构,最多可以看到类结构或代码结构,但对于分散的逻辑结构无法定义和简单地查看。而Leo却正好是以这些逻辑结构为基础的一个编辑器。在Leo中有许多的结点,组织成一种树型结构。一个结点对应一定的文本,文本中可以有对其它结点和特殊用于控制输出的标记。一个结点下还可以有子结点。如果在父结点上定义了一定的导出规则,就可以把相应的所以子结点按照父结点的结构和导出规则输出结果。父结点就象定义了结构的模板,子结点相当于模板变量的实例化。当然这种定义是可以递归的。而且结点的引用可以更复杂。这样,在编程中就是以定义和组织逻辑结点为基础,然后对每个结点进行编程。这种编辑方式可以使得逻辑关系一目了然,而且通过输出结点的特殊处理和结构安排,可以容易地对代码结构进行调整。

当然,从使用到熟练需要一个习惯的过程。

的确感觉不错。以前并不是很关注,因为许多东西都是靠记忆。但如何把这种记忆变成直观的形式呢?并没有仔细想过。现在看到Zoom.quiet的讲解感觉不错。而且许多人把他们的分析结果也存成了Leo的格式,可以从逻辑上直观的看到程序代码,而不是直面代码,这种感觉不错。看到Zoom.quiet收集的有python.leo和zope.leo,虽然版本可能有些老,但从别人分析的基础上再看代码可能直是很方便。而且推想大家的程序都这样写,那么理解程序可能相对简单多了。

如果NewEdit也支持这种功能,那么可能非常好。

后面是alex.dong做的关于lighttracker的开发介绍。那么lighttracker是alex.dong分析BitTorrent的tracker服务后的一个重新实现。原来的版本是采用twisted开发的,而alex.dong认为这是一个典型的web应用,完全可以考虑使用python的web framework来实现。当然,原BT的tracker服务还可以支持upd协议。不过既然是轻量的,可以不用考虑那么多。

而alex.dong采用web.py来开发,他认为web.py的好处主要有:

  1. 小巧,只要一个文件
  2. 封装层比较薄,比如对db,cookie,url映射等。模板采用cheetah。

因此对于快速开发非常方便。不过,有一些在演示中使用到的模块并不是python的标准模块,比如DBUtil,这些在web.py中使用,但需要单独安装的。因此在这方面,web.py还是有一些不足。原本alex.dong在用web.py实现了lighttracker之后,还希望使用django再实现一遍,但时间短,而且django的内容相对复杂,因此就放弃了。lighttracker实现了tracker的协议,如Announce, scrap, bencode。目前在sourceforge上创建有项目。

那么alex.dong同时还讲解了BT的工作原理和新出现的DHT(分布式HashTable),通过这种技术可以不通过中心服务器实现peer-to-peer的通讯(当然你总得有那么一次要与服务器连接成功进行初始化)。看来p2p的技术也在不停地发展之中。

然后alex.dong给我们运行,并进行了单元测试的说明。

效果不错,学到了BT的不少东西,而且也感受到了alex.dong的知识面很广。他除了使用python,平时主要以java和.net开发,而且是微软的MVP,水平可是不一般啊。

今天不错,因此会课从下午2点开始,到6点多才结束,回到家已经快8点了。许多东西还有待zoom.quiet进行整理。wiki页面访问。会后天成dreamingk希望下次我们去exoweb进行会课,真是期待啊。因为看到exoweb的工作环境与google有得一拼啊。

因为我在web方面主学的是django,因此对于web.py倒是有些想法。首先web.py应该算是一个比django还要简单的框架,而且它是在django之后出现的,并且许多东西直接学习的django。当然从功能上web.py没有django强大,从整体上说django很完整,比如ORM, template, url dispatch等。而web.py不是完整的ORM,只是对db的简单封装,当然我想也不能象django一样自动从Model生成表了(我没有用过web.py,我是这样想的)。web.py的模板系统采用cheetah,因此你还需要单独安装。session管理可能也不象django一样采用数据库。不过对于简单而且喜欢动手的人来说web.py可能不错。不过想比之下django的功能很强,但带来的问题的确,你要学习的更多。从使用者的角度来说,选择哪种web frame要看你的需要和你已经掌握的东西。强大的东西总是要学更多的东西。如果简单的东西够用,那么不一定要学更强大的框架。但如果你不想“事必躬亲”,希望更多的复用,还是强大一些的可能更适合。象我也是经历过不少框架的学习,如Karrigell, cherrypy等,到现在认为django比较适合我。学习不是一蹴而就,因此可以从简单入手,然后再了解复杂一些的框架。随着对框架的熟悉,终将实现运用自如,复杂不在是一个问题了。当然这一切都需要通过学习和实践来完成。

对于lighttracker的应用不算复杂。它只有两个表,因此在django中很容易生成。剩下的一些与tracker相关的处理,不管是用哪个框架都差不多,只是对于db和某些框架相关的可能有些区别。不过我想如果你熟悉django,还是很简单的。但简单永远是相对的。

发布时间为2006年7月29日。此次发布为正式版本发布,而不仅仅是在svn的trunk中。目前在官方网站可以直接下载到0.95版本。下载地址

发布信息可以看这里

发布信息写得很有意思,看一看原文:

This is the sexiest version of django ever. It would take another six months to list all of the improvements, feature additions and bug fixes we’ve put into this release, but the release notes document attempts to list the big changes. The overall theme is: Slicker, faster, easier, better.

简单地翻译一下:

这是以往Django中最迷人的一个版本。如果要列出所有我们所做的改进,特性增加和问题修复等可能还需要六个月的时间。但是发布说明文档试着列出了重大的改变。主旋律是:花哨(Slicker),快速,容易,更好。

写得的确很有意思。

为了从0.91迁移到0.95,那么你最应该看的文档是MagicRemoval的wiki文档

下面是release notes document中列举的一些重大的变化:

  • Django现在使用更统一和自然的过滤接口从数据库是获取对象。
  • 用户定义的model,函数和常量现在可以出现在定义它们的模块的名字空间中。(以前所有东西都被魔法般地被转换为django.models.*名字空间中。)
  • 一些可选的应用,如:FlatPage, Sites和Redirects等已经被拆分并且被转移到django.contrib中去了。如果你不想使用这些应用,你不再需要安装它们的数据库表。
  • Django现在支持数据库事务的管理。
  • 我们已经增加了编写自定义认证和授权后端的能力,针对于可替换用用户鉴别系统,如LDAP。
  • 通过一个新的"Manager" API,我们使得向model中增加自定义的表级函数变得容易。
  • 现在可以不使用数据库来使用Django。
  • 现在可以更清楚和自然地在model中覆盖save()和delete()方法,而不必需要挂接到pre_save()和pre_save()方法钩子上。
  • 独立的框架片段现在可以不必须通过环境变量的设置来进行配置。这样就容许,倒如,Django的模板系统用在其它的应用中。
  • 越来越多的框架部分已经被国际化了,因为我们已经扩展了国际化(i18n)的支持。Django的基础代码,包括代码和模板现在已经被翻译成至少31种语言。从阿拉伯语到中文到匈牙利语和威尔士语,现在可能使用你的本国语言来使用Django的Admin站点。
2006年07月21日

这是在邮件列表中看到的。Adrian Holovaty和Jacob将要参加在美国俄勒冈州的波特兰市的OSCON(开放源代码大会)大会。昨天Adrian在Google的芝加哥办公室做了一场Django的技术讨论会,在会上gogoler们问到何时可以发布0.95版,因此Adrian希望在OSCON大会期间可以发布,到时还希望有人可以参加并组织一个sprint。

当然希望是这样。

关于参加OSCON大会的blog可以看这里。OSCON大会将在2006/07/24-2006/07/28举行,即下周。看到Django开发小组的安排:

  • 周一,将由Jacob做一场关于Django的教学
  • 周三,下午的时候主要讨论Django的历史,核心哲学和一些“酷”的特性。
  • 周三,晚上召开Django的招待会,与Django项目的创始人一起交流,谈心。

在OSCON大会上关于Python相关的一些讨论可以看这里。看到内容安排真是一场盛会。

前一阵子在CSDN上看到有Guido van Rossum的中文版Blog,而且也在Guido的Blog看到有这一消息,当时也没有太再意。现在又在CSDN上看到它推出了国外技术大师的中文版计划,原来是有想法的。不管怎么样,看中文还是会非常方便,而且让大家了解到大师们的想法还是不错的。希望CSDN能做好。

现在已经有三个人的了:

Guido van Rossum:中文博客地址 英文博客地址
Phillip J. Eby: 中文博客地址 英文博客地址
Herb Sutter:中文博客地址 英文博客地址

不过仔细看一看,前两个都是Python的大牛啊。看到Python目前受到CSDN的重视了。而且CSDN也推出了不少Python的文章在首页,好事情。

2006年07月19日

下面演示动态处理CheckBox。请记住,我只是展示一些小例子,并不是为了详细介绍prototype.js的所有功能,而且许多的东西我也在学习在,希望把它们挖掘出来,但更重要的是大家自已应该去看一看源码,看一看都有哪些方法可以使用。

首先我要试验的Html文本(注意,为了发布代码所以有大括号全部为全角字符,因此你直接拷贝的话需要手工替换一下,不能直接使用)

<html>
<head>
<script src="prototype.js"></script>
<script type="text/javascript">
function onDelete(){
/*
 $$(‘#table input’).each(function (i){
  var v = $F(i);
  if (v){
   $(‘tr_’ + v).remove();
  }
 });
*/

 var s = $$(‘#table input’);
 var trs = $$(‘#table tr’);
 for(var i=s.length-1; i>=0; i–)
 {
  if (s[i].checked)
   trs[i].remove();
 }


function onAll(){
 $$(‘input’).each(function (i){
  if (i.type == ‘checkbox’)
   i.checked = true;
  }
 )

function onNone(){
 $$(‘input’).each(function (i){
  if (i.type == ‘checkbox’)
   i.checked = false;
  }
 )

</script>
<title>Tut01</title>
<body>
<table id=’table’>
<tbody>
<tr id=’tr_0′>
<td><input type="checkbox" name="idlist" value=0>1</td>
<td>2</td>
</tr>
<tr id=’tr_1′>
<td><input type="checkbox" name="idlist" value=1>2</td>
<td>3</td>
</tr>
<tr id=’tr_2′>
<td><input type="checkbox" name="idlist" value=2>4</td>
<td>5</td>
</tr>
</tbody>
</table>
<input type="button" value="delete" onclick="onDelete()">
<input type="button" value="all" onclick="onAll()">
<input type="button" value="none" onclick="onNone()">
</body>
</head>
</html>

在Firefox中打开这个文档,将显示一个表格,每行开头有一个Checkbox。如果选中某些Checkbox,然后点Delete,则对应的行将消失。如果点All则全部的Checkbox将选中,点None则全部的Checkbox将不选中。下面让我们看一看代码。

首先看几个按钮,每个按钮后面有一个onclick的定义,这样表示当点击按钮时对应的处理函数。因此三个按钮对应的不同的处理方法。

onDelete

这里我使用了两种方法。使用prototype.js删除一个元素很简单,只要定位到这个对象元素,然后执行元素的remove()方法即可。那么这里的关键处理是:如何定位元素。因为我们只能选中Checkbox,而Checkbox又位于tr标签中,因此需要有一种方法通过Checkbox来找到对应的tr元素才可以。对于第一种方法(注释掉了),我通过id来进行元素定位,因此需要Checkbox与tr有一种对应关系。那么这里我们可以让Checkbox的value属性为tr的id值,或者是一个合成值,比如tr的id为’tr_’+Checkbox.value。因此第一种方法首先执行$$(‘#table input’),它将查找id为table元素下的所有’input’标签。那么你可以看到这里我没有定义form标签,因为只是前端运行不提交数据,因此用不上。经过前面的学习,我们应该知道$$()函数会返回一个数组。在得到一个数据后,我们需要查看哪个被选中的状态,因此需要对这个数组进行遍历。prototype.js对数组元素提供了一个each()的方法,它接受一个函数作为参数,当从数组中每取出一个值时将调用这个函数。each()中定义了一个匿名函数,因为只有function (p)这样的形式,没有定义函数名。(很有意思的是javascript很象python,在函数中仍然可以嵌套函数。)这有些象 Python 中的 lamdba 函数。这个匿名函数可以接受两个参数,这里我只定义了一个,即传入的那个枚举值。第二个参数可以是一个索引,这里我没有用到就没有定义。因此你可以理解这里可以定义一个变长参数的函数。

在这个匿名函数中首先是var v=$F(i)。$F()是prototype.js提供的一个方便得到表格元素值的方法,相当于Form.Element.getValue。因此这句话就是得到当前元素的值。

然后if(v){$(‘tr_’ + v).remove();}。如果v为真,那么找到对应的tr元素,然后删除。这里tr元素的id是根据Checkbox的value值计算出来的。那么如果你了解javascript,你可能要问,为什么不判断Checkbox的checked属性呢,因为每个Checkbox都有值的,这样判断不是有问题吗?不错,每个Checkbox的确有值,但要注意我们并不是直接使用i.value来得到的值,而是通过$F(i)来得到的值,而$F()会对Checkbox和Radiobox元素检查它们的checked属性然后再返回。因此使用$F(i)时,如果没有选中Checkbox或Radiobox,返回值为null。所以可以这么判断。

不过这的确有一个问题,Checkbox的值必须与tr的id要对应,并且是可以计算的,而且每个tr还需要定义一个id,有些麻烦。因此我使用了第二种方法(非注释的方法)。

第二种方法的想法是,即然是一一对应的,那么顺序也是一一对应的。只要我按顺序找到一个Checkbox,如果它选中了,那么根据它的索引值,我就知道了对应的tr的顺序,因此通过索引值可以进行定义。这样首先得到Checkbox和tr的数组。然后对Checkbox数组进行遍历。注意,我没有使用each,而且使用了倒序。因为如果是顺序的,一旦删除,数组的个数会变化,这样就影响了循环的判断条件,因此我采用了倒序遍历的方法。而each是顺序执行的,因此不能使用。处理就简单了,不过这里没有使用$F()来处理,而是直接判断了Checkbox的checked属性。代码应该清楚了,就不用多说了。

onAll onNone

有了上面的讲解,我想这两个方法看起来就很简单了。

其实有许多内容是属于javascript的,而我也不可能讲述所有的细节,建议买本javascript的书学习一下。

 

2006年07月17日

Python 2.5版就快要正式发布了,它的中文教程已经由刘鑫和李梦夷翻译成中英文对照。下载地址

由郭勇转为PDF格式。

感谢!

学习web的开发已经有一段时间了,越来越感觉 Ajax 技术的发展也需要投入精力,因此买了一本 Javascript 的犀牛书《Javascript权威指南》,好厚的一本书,也是不错的一本书,作为学习的资料和参考都不错。不过我并不希望直接从原始的 Javascript 开始,因此有必须选择一种 js 框架。简单地比较一下,我目前选择了 prototype.js ,为什么,也许有以下原因吧:

  1. prototype.js 比较轻量级,看源码也方便,应用范围很广,而且基于prototype.js开发的js库不少。不过因为prototype.js是由ruby团队开发的,因此有许多的语法很象ruby。
  2. Mochikit是一个语法象python的js框,一样是轻量级的,它在TurboGears中受到使用,不过扩展较少,先放一放。
  3. dojo有些庞大,虽然它可以分包导入,不过教程较少,而且不象prototype.js提供了许多方便的函数,当然功能是很强的,也先放一放,也许下一个学习的目标就是它吧。

Ajax如何在Django中应用呢?邮件列表中经常有人提出这个问题,我也一直在思考。James Bennett在一篇blog讲到,django在支持ajax上已经足够了,作为一个web程序员不使用javascript就不能算是一个web程序员。现在django提供了一个叫serializer的模块,可以将QuerySet封装为xml, django, python等格式的数据,因此作者认为django对ajax的支持已经足够了,不需要象其它的框架一样提供一些helper的封装来自动生成一些ajax的代码。不过Ian Holsman另一篇Blog认为虽然学习Javascript很重要,但有时还是需要节省一些工作,因此可以自动生成最好。我认为也是,javascript最好学习,不过有一些辅助性的东西能用也不错。不过就是想封装也要相对熟悉才行,而且有些工作可能还是需要手工来做,所以学习javascript的确也很重要。

因此我打算把学习prototype.js的一些过程记录一下。

在学习之前建议使用Firefox,并且安装Firebug 0.4和IE Tab插件。前面可以查看js,css的错误,还可以在运行时输入javascript代码进行调试,还可以动态查看dom树。后者可以方便转到IE进行浏览。这两个插件对于Web开发会非常方便。

我记录的也许都是一些很具体的处理,主要是为了简单。真正想很精通prototype.js的话,可能还需要经常看一看它的源码。另外多看javascript的手册也很重要。

首先提供几个参考:

prototype.js http://prototype.conio.net/
prototype.js 1.4开发指南 http://www.sergiopereira.com/articles/prototype.js.html (有中文版本)
Painless JavaScript Using Prototype

不过要声明一下,我目前关注的不是各种Effect效果,而是前端与后台的交互,因此对于数据的更新、提交、删除更为关注。同时有些可能是属于Javascript的东西。

在准备好之后让我们开始学习如何定位元素。

写一个tut00.html文件:

<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<table id="table">
<thead>
<tr><th>column1</th><th>column2</th></tr>
</thead>
<tbody>
<tr><td>1,1</td><td>1,2</td></tr>
<tr><td>2,1</td><td>2,2</td></tr>
</tbody>
</table>
<a href="http://www.donews.net/limodou">limodou donews blog</a>
<a href="http://www.sina.com.cn" class="site">sina</a>
<form id=’form’>
<select name=’select’ size="4">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<input type="text" name="input" />
</form>
</body>
</html>

可以看到,在script中我引入了prototype.js。目前正式的prototype.js版本是1.4.0,在svn中有最新的版本,可以下载。我使用的是svn中的版本,是1.5.0_pre1。建议大家都使用最新版本。

在Firefox中打开它。那么它只是显示一个表格(table),几个链接,和一个表单(form)。好象什么也做不了。的确是,但我们将在Firebug中对它进行操作。

1. 激活Firebug

需要确定你的Firebug已经激活,如果安装了Firebug插件,在firefox的右下角有一个小图标,或者是一个禁止的,或者是一个对勾,或者是一个红叉。点击它将打开Firebug的窗口。上面有三个Tab页,分别是:Console, Debugger, Inspector。进入Console,窗口最下面有一个 >>> 的输入行,它可以输入js命令。

2. 如何定位

定位有许多种方式,DOM提供了两种getElementById,它可以返回一个id为指定值的元素。getElementsByTagName,它可以返回tag name为指定值的元素列表。这两种都是DOM提供的。DOM就是装入页面的文档树,它的根元素是document对象。让我们试一试:

>>> document.getElementById(‘table’)
<table id="table">

可以看到,找到了id="table"的table元素。

>>> document.getElementsByTagName(‘a’)
[<a href="http://www.donews.net/limodou">,<a class="site" href="http://www.sina.com.cn">]

可以看到返回了一个数组。

那么prototype.js对于document.getElementById这个方法提供了一个简单的函数,$(),并且它可以传入多个参数,比如:

>>> $(‘table’)
<table id="table">
>>> $(‘table’, ‘form’)
[<table id="table">,<form id="form">]

很方便吧。因此定位元素的第一种方法是通过id。因此使用这种方法需要在元素中加入id属性。并且id属性在整个文档中是不能重复的。

第二种方法是对tagname调用document.getElementsByTagName来得到一个数组,根据元素的顺序来得到元素。这种方法对于批量处理有帮助。

prototype.js提供第三种方法是使用document.getElementsByClassName:

>>> document.getElementsByClassName(’site’)
[<a class="site" href="http://www.sina.com.cn">]

它可以根据一个class属性来得到一个元素的列表。

HTMLDocument还提供第四种方法,可以通过name属性来得到一个元素列表:

>>> document.getElementsByName(‘input’)
[<input type="text" name="input">]

第五种方法,是prototype.js提供的$$()函数,它的功能很强大,可以以css selector的写法来定位元素列表:

>>> $$(‘#table’)
[<table id="table">]
>>> $$(‘#table tr’)
[<tr>,<tr>,<tr>]
>>> $$(‘.site’)
[<a class="site" href="http://www.sina.com.cn">]
>>> $$(‘a.site’)
[<a class="site" href="http://www.sina.com.cn">]

如果你对CSS Selector不是很熟悉,建议你找些资料看一下。

还有可以使用DOM提供的其它的方法,如firstChild等进行相对位置的查找。

找到一个变量是第一步,然后才是对它进行操作。

通过这个例子可以帮助你了解Firebug的强大功能和简单的元素的定位,搜索等。比如通过id, name属性,classname属性等都可以定位元素,如何使用要看具体的场合。

除了这些,还有一些定位的方法,比如document提供了forms等属性,可以定位一些特殊的元素。在一个form中可以通过form.name来定位一个输入元素。如上例:

>>> form = $(‘form’)
<form id="form">
>>> form.input
<input type="text" name="input">

这样通过name也很方便。

2006年07月06日

Django现在增加了一个目前还处于开发中的对象序列化的支持。你可以通过新的文档 serialization 来了解它的内容。使用很简单,举文档上的例子:

from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())

在文档上说serialize需要一个序列化的格式和查询集(QuerySet)。目前支持的格式有xml, json, Python。其中json使用了simplejson模块。

因此使用它进行Ajax的开发要方便一些。

不过,有一个问题是它只支持对QuerySet的序列化,如果是单个对象或简单的Python变量则会报错。因此上对于简单的情况可能还需要自已来做。

2006年07月03日

今天在postshow.net上看到一个链接,可以生成金币的图案,试了试,我的结果如下:

有趣吧。