2006年03月07日

学习django很长时间了,woodlog也一直在开发,但开发的进度比较缓慢。我在思考,到底哪里受到影响了呢?想来想去,是模板,是model,是什么?我认为,现在我最大的问题就是界面(UI)了。也许有人会说,UI有什么了,先做个简单的,然后再完善。不错,是这样,但就是简单的生成都感觉麻烦。这也许是我特有的开发方式吧。我是一个懒惰的人,我不喜欢手工去设置界面,虽然大部分时间就是这样做的,我希望有一些简单的方式让我开发出一些过得去的界面。但web UI与 GUI 不同,它没有很标准,比较漂亮的UI控件,比如Tab之类的。而且许多的定位需要靠CSS,远不如GUI来得方便。对于一个开发web很熟练的人可能不会有任何问题,他们可以一上来就画模板,写CSS,写View,一切可能是井井有条。但我对于web还不是很习惯,理论学了不少,基础知识也都有,但总感觉到麻烦。这就是我最大的问题。有些东西,手工做是麻烦一些,但只要坚持成果一样出得来,但我还是希望能省则省。这不写了一些自定义tag,还写了一个生成简单的menu的tag,还写了简单生成form的代码和fieldset的代码,都是为了以后修改方便和开发方便。但目前的积累不够,大部分时间在考虑如何将界面与后台的处理结合起来。

如果手工做的确没有什么难度,对于 model 的设计反倒不感到困难,主要还是显示,和保存,在处理时如何将model的对象及字段与ui相关联,保存时如果将数据取出来,再有就是值的校验。现在还没有怎么考虑Ajax,到那时候调整还会多一些。

Django的admin功能是不错,但与model的关系过死,如果想使用它的代码自已去处理,可能拷贝粘贴的代码不少,而且还不是很通用。因此我希望有一种与model无关的处理方式,但许多东西做起来就困难了。如model之间的关系的处理。在django中可以自动将相关的内容生成在一个界面中,这样在一个界面就可以完成多个model的处理。而如果自已做,就不太容易了,主要是关系如何获取。django和其它的orm有不同的api,目前来说没有一个更高层的封装是很困难的,因此这部分的处理很麻烦,也没有思路。当然可以让用户自已定义,也许不是很困难。要做的就是一个接口。这部分工作会在开发中继续思考。有些东西想得不是很完善。

做界面除了没有很漂亮,标准的web ui控制外,再有就是css的处理了。一方面它需要放在html文档的head标签中,另一方面你还需要在body中给相应的tag设置id或class。这些内容使得构造一个html页面显得很松散。当然这种方式更适合非程序员来做。不过,作为一个程序员来说,总是感到没有使用程序自动生成来得爽。为什么django的admin让人感觉不错呢?我想可能大部分人使用django都是程序员,他们习惯让程序来工作。而自动的admin正好满足了他们的要求。只不过,这个admin在复杂的情况下不够用而已。

那么我目前主要的工作可能还是在界面生成这块,再思考思考吧。首先是做一些标准的web widgets,使用模板来定制(menu,easyform和fieldset已经是这样了),然后再考虑布局的一些问题。再就是整理一些标准的css布局。这样就是一个基础了。慢慢来吧,反正没人催 :)

在我的建议下,Stani 创建了一个新的位于google上的讨论组,用于pyxides的讨论。地址在这里。有兴趣开发IDE的可以加入学习一下。此项目目前还在讨论中,处于前期准备,正好是加入和学习的好时机。

2006年03月06日

django 的模板中,如果你需要定义一个变量,怎么办.而且这个变量希望象 Python 的数据类型一样,甚至可以使用 django 的 Context 的内容就更好了.于是我自已写了一个,这是在仔细地研究了 django 的模板代码和一些示例子后.首先看一下代码.

from django import template
import re

register = template.Library()

class ExprNode(template.Node):
    def __init__(self, expr_string, var_name):
        self.expr_string = expr_string
        self.var_name = var_name
   
    def render(self, context):
        clist = list(context)
        clist.reverse()
        d = {}
        for c in clist:
            d.update(c)
        context[self.var_name] = eval(self.expr_string, d)
        return ”
   
def do_expr(parser, token):
    try:
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents[0]
    m = re.search(r’(.*?) as (\w+)’, arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    expr_string, var_name = m.groups()
    return ExprNode(expr_string, var_name)
do_expr = register.tag(‘expr’, do_expr)

怎么用它呢?

  1. 如果想使用一个 templatetag ,首先要把它放在一个app中的templatetags目录下,然后将这个app在settings.py中设置一下.
  2. 然后在一个模块中先使用load命令装入它.比如上面的文件名为utiltags.py,则load的语法为:

    {% load utiltags %}
  3. 然后就是调用expr的语法了,如:

    {% load utiltags %}
    {% expr 1 as a %}
    {% expr 2 as b %}
    {% expr a+b as c %}
    {{ a }}+{{ b }}={{ c }}

从上面可以看出,表达式中可以是一般的python语句,同时还可以使用定义在 Content 中的变量.基本的语法是:

{% expr expression as var_name %}

 下面再让我把程序的大概意思介绍一下.

  1. m = re.search(r’(.*?) as (\w+)’, arg)

    用于将标签文本按 * as * 进行拆分,这样 as 之前就是一个表达式,而 as 之后就是一个变量名。即我们在后面将要把算出的表达式的值保存到指定的变量名中。
  2.         clist = list(context)
            clist.reverse()
    context本身是一个对象,我们将要把它作为一个名字空间进行使用。因此需要转换为字典。但 context 象一个list一样,每个list中才是一个字典。也就是context首先是一个栈,然后栈元素是一个字典。因此,先将context转为一个list,然后反向排序。为什么?因为为了保证新的元素不被旧的元素覆盖(栈顶才是最新的,而这里的栈顶是从0开始的),因此反向排序是为了新元素放到最后进行处理。
  3.         d = {}
            for c in clist:
                d.update(c)
    生成一个字典,将作为名字空间在eval函数中使用。
  4. context[self.var_name] = eval(self.expr_string, d)
    计算结果并将结果存入 context 中去。

为了发布此文,半角大括号我使用了全角进行替换,请注意。

2006年03月04日

仔细看 django 的代码可以发现许多的好东西.这不本文将讲一个curry的函数.不知道怎么翻译为好.它位于 django/utils/functional.py.函数的定义为:

def curry(*args, **kwargs):
    def _curried(*moreargs, **morekwargs):
        return args[0](*(args[1:]+moreargs), **dict(kwargs.items() + morekwargs.items()))
return _curried

它的工作就是一个decorator的方式.它的主要作用是将原函数预置一些参数,然后返回一个新函数.这样新函数只需要传入原来没有预设的参数.这样在某些情况下可以简化一些处理.特别是有时为了通用我们定义了一个函数有许多的参数,但调用者却只使用几个参数进行调用,特别多的是在GUI编程中的事件处理方法中.为了在事件处理中使用这个多参数的函数,使用curry可以解决这个问题.

举例如下:

>>> from django.utils.functional import curry
>>> def a(a, b, c):
…     print a, b, c
>>> b = curry(a, ‘a’, ‘b’)
>>> b(‘c’)
a b c

第一个参数需要是一个函数对象,后面是预设的参数值,可以是tuple参数和关键字参数.

不过它使用起来还是有一定的限制,主要是它的参数处理.从上面的源代码可以看到,它对于tuple参数和字典参数是不能混在一起的.特别是对于tuple参数,它是采用追加的方法,因此预设参数时只能是从前向后,中间不能跳跃.比如你想预设上面的a, c参数,但是做不到,其实还是预设了a,b参数.而对于字典参数却没有关系.

这里要注意的是,所谓字典参数就是指有缺省值的参数.

2006年03月02日

django 最近的变化不可谓不大,这都是托 pycon 的福.许多东西在改进.下面把我了解的一些说一下,等版本正式稳定了,教程都要改了:)

  1. 取消了 django-admin 的 init 命令.我们知道,init是用来初始化数据库的,然后以后通过install来增加app的model所对应的表.现在取消了init命令之后,增加了一个新的叫syncdb的命令.它就更好用了,它会检查所有安装的app(即在settings.py中的INSTALLED_APPS中的配置项),然后创建那些还不存在的表.因此使用它就可以自动创建相关的表.有人还建议在执行时可以装入数据,不过还没有看到这个变化.
  2. 增加了一个新的middleware,需要在settings.py中设置.

    ‘django.contrib.auth.middleware.RequestUserMiddleware’

    这个是用来处理用户认证的.django已经开始可以使用外部的认证方式了.具体如何做我还不清楚.
  3. 增加了事务的处理.这还是我看到的一篇blog说的这事:Django Gets Transactions

还有许多的变化,有些我也不是很清楚.每天 svn 的修改都非常多.

2006年02月28日

现在在 wxPython 的邮件列表中正在开始一个非常有意义的项目,那就是由SPE编辑器的作者Stani发起了几大 wxPython 的编辑器的作者一同开发一个新的编辑器的项目。有人建议是做成一个IDE,不管怎么样都行。已经包含了象SPE, NewEdit, DrPython, ActiveGrid, 等人员的加盟,还有其它相关的一些项目的作者,如一个UML模块的作者,Eric3的作者也在关注,还有Robin这位wxPython的大佬也在关注。讨论很热烈,目前基本的想法是先创建一个精巧,稳定的核心,然后展开。但具体的细节还要等创建项目之后,可能会有一个wiki进行讨论。

不过使用英文讨论真是很麻烦,看着费劲,写着费劲。不过到是可以认识不少人,还是不错。有兴趣的也请关注,这将是一个非常好的学习的机会。有这么多经验非富的人参与,前景还是不错。

2006年02月27日

正好我们的CPUG的大会与PyCon大会有一天是重合的,也许是一个巧合吧。时间在 2006/02/26 日。参加人数不多。在会我先是由我主讲了关于 django 和  正在开发的 woodlog 系统。然后由 Zoom.Quiet 宣讲了关于 CPUG 的发展历史,2005年工作的一个介绍。再接着就是对目前存在的问题提出,然后大家讨论。在会上主要认定CPUG的目前阶段的主要工作仍然是大力宣传和推广 Python 语言,多与企业、学校联系,尽一切可能的机会多宣传 Python 。另外鼓励原创文档,翻译文档的创作,同时啄木鸟主机已经有一些自动发布的功能可以方便发布系列文档。对于项目目前仍以个人推动为主,但希望有强有力的项目作为CPUG的一个宣传的亮点。

在会上大家提了许多好的想法,一方面需要加强成员之间的交流,倡导有经验的成员更多的分享成功与问题。对于新手倡导积极的交流。

会课的语音下载页面

讲课的S5幻灯也在上面的页面可以下载。

因为繁忙,甚至连重大的 Python 大会都没有来得及报到。

Python大会在Dallas/Addison Marriott Quorum Hotel举行。正式的会议时间是 2/24 – 2/26 日。因此到本文发布时主要会议已经完成。内容可谓是非常多,安排得也很紧张。日程安排。 从2/27-3/2日是常规的sprint日,也就是大家在一起实际地解决一些问题,在短时间内让大家一起做些东西出来。

关于大会有一个网站可以看这里

我是没有机会参加的,不过有人在网站记录了一些情况。看这里。不过这个报道是位于blogspot上的,因此一般你是看不到的,但可以通过bloglines订阅。或在 http://www.planetpython.org/ 看到。Guido 作了主题发言,特别是讲述了一些关于 Python 2.5 版的一些进展和变化,预计新版本将在今年9月发布,真是一个好消息。具体的内容还是希望大家去上面的链接看一下。

关于 sprint 的安排参见这里。其中关于 django 的在这里。上面有一些计划,都是不错的,象:

将magic-removal 与trunk合并。事务。模式的派生(即model的继承)。多种后端认证,如OpenID。创建Django的标准应用库。实现Oracle/ODBC的数据库后端等。当然题目都不错,但到底是哪个被选中,还要看他们的具体安排。

Eugene Lazutkin参加了大会,并且拍了不少照片。Blog记录地址在这里。Flickr 地址在这里。选一些照片出来:

Guido不知何时留起了大胡子。不知道是不是因为看了孟岩所写的《胡子决定编程语言运势》,反正是留起来了。大家通过上面的链接看照片时可以看到 Guido 的衣服换了几次,有Google的,有Powered by Python的。

Andrew Kuchling,我们看到的许多Python的文档就是出自他之手。

左边不知道,但右边是Ian Bicking。看脸型,如果刮掉胡子还比较帅啊。

右边就是Django的创始人之一:Adrian Holovaty。表情总是这么害羞啊。

Jacob Kaplan-Moss是django的另一位创始人。

大家自已去找吧,很多有趣的东西。

2006年02月17日

一直想做一个 Blog 系统,想在啄木鸟主机上装一个。为什么,因为 Python 真的没有一个好的 Blog 系统。在做 NewEdit 项目的时候,我似乎明白一些道理:

  • 经验要靠做的
  • 自已的才是大家的

学习这件事,光看书不行,要实践。实践的目的是为了真正理解,而真正理解就是一想就有,已经在头脑中留下痕迹,必需要对你的大脑产生一定的刺激才可以。强度不够都不行。因此要不停地实践。在实践的过程中你一定要积累。怎么积累,代码写出来了,就是积累,以后可以参考。文章写出来的也是积累,同时对你的思维是一个整理的过程。说白了,就是要有拿得出手的东西,可以保存起来的东西。不然,时间长了,很可能就忘了。积累是一个漫长的过程,只有坚持才能有收获。积累还是一个寻找的过程,寻找和记录下你认为有用的东西。积累还是一个考虑的过程,你会琢磨,哪些是有益的积累,哪些是无益和积累。在这种积累过程中你会形成自已的风格,自已的思维方式,从而决定的你要走什么样的道路。

许多东西不好用怎么办。自已做。有些东西可以与别人合做,有些东西可以自已做。合做的东西总有自已不是很清楚的东西。而自已做的东西,除了遗忘,都是清楚的东西。因此自已做的好处是你会很方便地将你的经验应用到其经的地方,而且可以无限制地使用你的成果,不用担心其它的问题。自已的东西你是最熟悉,也是使用起来最顺手的。从而可以大大提高你的生产力。

如果你喜欢分享,首先你要有积累才能贡献给大家。自已做的东西最容易积累,好与不好,可能对别人都有帮助。

那么这个 Blog 系统也算是我学习 django 以来做的第一个大点的东西。原本想得功能挺多,多用户,Ajax功能,多级分类,多级评论等等。但真做起来才知道问题很多,有经验的问题,也有 Django 本身的问题。因此只好把功能简了又简。现在终于有一个单用户,可以做一些简单处理的 Blog 系统了。有兴趣的话大家可以看一下。这个 Blog 功能还很弱,纯当是学习了。如果可以的话,慢慢完善吧。

SVN 地址: http://cvs.woodpecker.org.cn/svn/woodpecker/zqlib/tangle/limodou/blog

2006年02月16日

学习一门语言的原因有很多,基本上可以归为:为了谋生,为了兴趣。

谋生是一个很现实的问题。许多人都想学好编程,目的是为了找一个好工作。在网上我看到一篇 Blog 是关于 Snakes & Rubies 的会议发言,有人记录下来了一些重点,其中有几句我感觉很好的:

On using "not mainstream" languages:
Adrian: "Our response was: With PHP people learn that because they
want to get jobs. With Java they learn that because they take computer
science courses. With Python you learn it because you love it. Because
you want to experience the beauty. I’m sure it’s the same way for
Ruby. If I’m hiring a Python programmer the chances are that the
person is good."
David: "I totally agree."

编译成中文为:

当谈到"非主流"语言:
Adrian:"我们的回应是:人们学习PHP是因为要得到一份工作;人们学习Java是因为他们选修了计算机科学这门课;人们学习Python是因为他们爱这门语言,因为他们追寻美,(我相信这对Ruby也是适用的)。如果我雇佣了一个Python程序员,他很有可能是优秀的程序员。"
David:"完全同意。"                             由bSword译

于是我也无聊,想发到CSDN上去,但没想到选为非技术话题,结果贴子跑进了灌水乐园了。真有人回复,见下:

这些都是废话,最实际的需求就是老板需要。
喜欢又不能当饭吃,不要用老外的价值观来对比,别人可以写一个月程序活半年,我们行不?

还是要吃饭的
中国和外国不一样

楼主不知道有中国特色的社会主义吗?

诊断:楼主目前活在精神世界中

而我的回答是:

吃饭的话我用c,java。也许还有可能是python。

请注意,这里并没有说我是否需要靠python来吃饭。你完全可以只把它当作一个兴趣。

其实本就是一种感悟,生活要放得轻松些才好。结果许多人看到Adrian的第一反应就是:挣钱。不可不说这的确是中国的一种现实,也是中国在开源方面不足的地方。但这些并不是我想说的。我想说,生活中除了工作挣钱,你还可以有其它的爱好,甚至是理想。也许这些理想不能成为现实,但正是因为有了许多美好的理想生活才不会那么单调和乏味,除了工作挣钱你还可以有许许多的有意思的事情去做。如果你认为这种生活不现实,那只能承认你的生活并不让你满意。

在 Python 的邮件列表中至少还有人同意Adrian的话。同时也证明了物以类聚,人以群分的简单道理。