为什么我从Ruby on Rails转向Django又转回来星期五, 十一月 9. 2007趁有时间,再翻译一篇文章,原文地址:http://blog.carlmercier.com/2007/01/30/why-i-moved-from-ruby-on-rails-to-pythondjango-and-back/ 在2006年3月份的时候,我决定完全重写Ajaxwhois.com网站。我已经学了很长时间的Ruby on Rails,知道它就是最合适的平台。Ruby on Rails可能对刚刚从Java或.Net转过来的程序员有点难用,但是只要很短的时间,你就会适应它。 透明的代码生成,糟糕的IDE工具,还有更坏的,没有好用的调试器,这些导致我转向Ruby遇到了一些困难,我已经习惯了Visual Studio .net,习惯了它的智能感知。我好怀念它啊。 每一个使用Rails的新手都会很快的明白它为什么会这么流行。首先,既便我还不是一个太熟练的Rails程序员,我现在使用ROR的开发效率仍然能够达到asp.net和C#两倍以上。这要多亏了MVC(Model, View, Controller),DRY(Don't Repeat Yourself)和约定高于配置的理念。所有的数据库处理代码都已经自动生成(甚至不需要运行任何代码生成工具),还有自带的模板系统和Ajax支持。 用ROR的日子是美好的,用的越久我就越喜欢它,直到2006年的8月初。我已经准备好了Ajaxwhois网站的2.0版本,准备上线了。认识了很多Rails专家,我以为把我的程序发布到生产环境服务器是件很简单的事,但是,我错了。虽然安装Linux(Ubuntu Daper Drake 64位)、Lighttpd、Mysql和Mongrel都很正常,但是我遇到了很奇怪的问题,主要是Mongrel的问题。有时候,Mongrel进程就那样死掉了,进程列表中看不到,也没有任何明确的原因,这时候服务器还没有任何流量,因为我还没把DNS转过来。还有的时候,Mongrel疯狂的占用CPU到99%,我不得不手动Kill掉它再重启。 经过一番搜索和无数次的重装,我发现Mongrel跟64位Ubuntu不太兼容。Mongrel打过这个补丁,但是并没有解决我的问题,它还是会每天死很多次,而且我找不出哪里出的问题。问了几个Rails专家级的朋友,他们也都没有办法,我受不了了。 我不能再浪费更多的时间了,于是我拿了本Python的书,并且又一次重写了整个网站,在Python里我使用了Django框架。我从来没有Python和Django的编程经验,但是转换是相当容易的,因为Ruby和Python的语法很多地方很想像。 Python和Django给我的体验非常棒,每个开发人员都应该考虑一下。不过,我很快就怀念ROR了。Ruby支持真正的private/public/protected方法(Python只是用它的命名方式模拟一下),而且它的语法更宽松(Python里面每个方法都要写(),烦死我了)。Django不像Rails那么简单,需要更多的代码完成相同的工作。Django还有些小问题让人觉得很不爽,比如需要手工传递参数到view,数据库处理也不像Rails的ActiveRecord完成的那么漂亮。这种问题还有很多。 另一方面,Python比Ruby要快,而且内存占用更少。而且我真的爱上了Python的缩进语法。更重要的,Python和Django工作正常。我从来没有遇到过像Rails那样当机的问题。 那么,为什么我在下个项目的时候又回到了Rails上呢?三个字:FUN。我觉得ROR用的更爽,社区庞大活跃而且很有用。可用的Rails插件很多而且核心代码的改进相当快。Rails需要的代码量更少,没有self.__awkward_method_calls()这种东西,有内建的Ajax和REST支持,更复杂的数据库操作和模板引擎。 那死机的问题怎么办呢?还有速度的问题呢?嗯,死机的问题消失了。别问我怎么弄的,我也不知道,它就那样消失了,我发誓!某个时间某个问题的修复解决了我的问题。但是速度的问题仍然是Rails的一个软肋。使用缓存和优化代码可以解决很多情况下的问题,而且Ruby的作者Matz正在努力的写成一个新的虚拟机,以便让Ruby至少像Python那样快。 我的建议是:两个都试用足够长的时间,才能发现哪一个更适合你。如果你已经有Python的编程经验,Django当然是最好的,但是如果你有Java/Perl/Smalltalk背景,ROR可能更合适。 PS:我的Rails问题也不能全怪Mongrel,因为我也不知道具体是哪里的问题。Mongrel是个优秀的软件,我真心的推荐它。只是如果你使用64位Ubuntu的话,盯紧一点! 升级Django到svn trunk需要做的工作星期五, 十一月 2. 2007花了不少时间,走了不少弯路,多了不少Bug,总算是把理财易的Django升级到svn trunk版本了,值不值得还不知道,不过,用新的总归没什么坏处,而且,1.0已经不远了,现在做好准备也不错。 首先删除原来的Django 0.96版的安装,全新安装svn trunk版,启动服务器,打开首页,出现一堆错误。首先是前面提到过的那个用来做“记住密码”密码功能的自定义的DualSessionMiddleware,它引用的页面发生了变化,SessionWrapper类已经不存在了,所以启动报错。暂时修改Settings文件,使用默认的session middleware,OK,通过了。然后提示_()函数不存在。这个是gettext函数,用来做多语言界面的,查了一下 兼容列表,果然,这个函数被移除了。于是在所有出现这个函数的文件里加上from django.utils.translation import ugettext as _,通过。进留言板,进不去,提示编码转换错误,什么"ascii can not decode”什么的,跑到官网一查,说是什么修改了对Unicode字符串的处理,现在整个系统各个环节的Unicode已经统一(大概是输入,转换,和输出)。结果是:需要把所有的用%来拼接字符串的地方,加上u标志。比如s='用户名%s不存在' % username,如果这个username是中文,这里就会报错,一定要把前面的这个变量加上u,标明这是Unicode变量。 改了N多地方,总算又通过了,然后继续测试,发现另一个地方又是转换错误,但是这里只是把一个包含中文的数组用join的方法串起来,我去哪里加这个u呢?想来想去,找到了定义这些中文的地方,在每一个中文变量的前面加上u,通过了。现在,代码变得相当丑陋了。(为了给省和市的名字加这个u,做了近200个替换,也不知道有没有留下后遗症)。 想到的地方都解决了,就更新到了服务器上。结果第二天有人报告无法注册,原来检查用户名是否符合规则的地方也变了。以前获取到的用户输入都是UTF8的,用正则来判断是否包含中文,需要先转换成Unicode,于是对输入字符串做了一个decode('utf8'),现在,这一步变成了多余的,所有的输入本来就是Unicode的。(但是读写数据库的时候似乎会自动转换成UTF8,否则写入Mysql应该会报错。) 后来又想到WAP那边也有中文的处理,打开手机一试,果然如此,中文用户无法登录了。以前的解决方案是利用客户端的能力,把输入的字符串编码成URL模式,中文会变成%D7%B7这样的字符串,拿到以后用urllib.unquote来解析出来,然后,如果客户端是UTF8的,要用decode('utf8')来处理,如果客户端是gb2312的,要用decode('gb2312')来处理。(虽然我在所有的WAP页面里都指定了编码是UTF8,但是在我的Palm上使用Blazer浏览器,仍然是GB2312编码的。)因为无法预知客户端如何编码,所以用try做两次解码。但是现在,不管用哪个,都会报错。 在这个问题花了许多时间,尝试各种各样的解码规则,都失败了。后来终于想到了问题所在,在不使用任何解码的情况下,服务器端接收到的是%D7%B7的字符串,说明这一步是正确的,然后,在unquote以后,文字就已经变成乱码了,按理说,应该只是把%变成\x而已。这一步实在是出乎意料,因为按理说收到的都是英文字符串,难道对英文字符串的处理也会因为编码而不同?经过测试,还真是如此。以前request.get拿到的字符串是没有编码的,也就是说%D7%B7就是作为一个普通的ascii字符串,但是现在,这个字符串被作为了Unicode字符串。unquote方法在解析Unicode字符串的时候,得到的结果是错误的。知道了问题,答案就找到了。先对输入的字符串做一个encode('ascii'),再进行unquote,啊,终于结束了。 另外,系统在从0.96更新到0.96.1的时候(也就是打了那个多语言方面的补丁以后),多语言功能消失了。IE的用户看上去是正常的,但是Firefox的用户看到的都是英文。(如果Firefox的语言选项里只有zh和zh-cn,那他看到的是中文,如果有了en,哪怕是在最下面,还是会显示英文界面。)跑到google group里去发了个帖子,最后得到了官方的回复,这是他们的一个Bug,在修改的过程中出错了,而且,只有zh-cn,zh-tw和pt-br出错,zh-cn需要改成zh_CN,在conf下面的default setting文件里。算了,还是不要改了,反正暂时关了多语言也没关系,等官方版本修改了这个再说吧。 11月4号更新:今天根据用户的反馈,测试了一下,发现Opera访问WAP的问题还是没有解决,中文编码不正确。不只是WAP上,用PC上的Opera登录WAP站,它的中文也有问题。在Postfield里面使用:e标识符以后,其它的浏览器都会根据自己的编码(gb2312或utf8)对中文进行URL编码然后发送,但是在Opera上编码以后,却丢了一半的值(一个汉字经过GB2312的URL编码以后应该是%D7%C7这样的两组值,但是Opera却只返回了后面的这一个,解码当然就不对了。 改了几种编码都不对,后来把:e的编码方式去掉一试,居然成功了。看来Opera对中文的兼容性已经远远超越了其它的手机浏览器,能够不编码发送完整的中文到服务器端。但是把:e去掉以后,别的浏览器又不对了(Palm上的Blazer会丢掉最后一个汉字)。不过既然知道了具体的现象,也就有解决办法了。通过服务器端判断User_Agent是否包含Opera字符来判断用户使用的是不是Opera浏览器,如果是,在生成页面的时候就不要添加:e标识符。经过测试,PC上和Palm上的Opera Mini都已经可以正常使用中文了。 Django:更简单的实现记住密码功能星期一, 十月 29. 2007Django的设计里,Session的保存是借助Cookie的,Cookie的保存默认有两种周期,浏览器生命周期和14天周期。这两者的选择在settings.py里面的一个参数,设成True就是前者,设成False就是后者。但是,我们通常的需求是用户登录的时候可以选择是否记住登录,如果不选就是前者,如果选中,就使用后者,但是Django却没有留下这个接口。 在我以前的文章里面,是通过直接修改Django的源代码,改了它的sessionMiddleware来解决的,今天在浏览它的google group的时候,终于找到了一个比较正规的方法。其实其原理跟我那个方法是完全一样的,修改sessionMiddleware,让它在设置Cookie之前从当前的session里面读取一个值,看看是否要记住密码,从而控制生成哪一个周期的Cookie。 但是他的做法就比我要高明了,我的做法直接修改了Django的源代码,所以导致每次升级的时候会很麻烦,因为会覆盖以前的修改。但是他的做法是自己重新写了一个sessionMiddleware,基本上,这个文件应该就是直接把原来的拷了出来,然后做修改。只要在settings文件中指定这个middleware的类,让你的项目使用自己的这个就可以了。这样,系统自己的就完全被忽略掉了。 这个博客不能贴代码,需要看源代码的去我的博客堂地址吧:http://unfish.cnblogs.com Python Django WAP中文乱码星期一, 四月 30. 2007虽然不太想在这里写技术性的文章,不过为了凑数,同时增加点关键字,还是写点吧。 理财易在运营的过程中,会员提出是否可以开发WAP记账的功能。虽然别的记账网站都已经有了这个功能,但是我一直对这个不太感冒,因为我自己都没有用过WAP功能。所以,我觉得别人也不太可能用这种东西。不过既然有人提出来了,就研究一下吧。 开发过程还是比较顺利的,Django的模板系统可以套用在任何框架上,所以只用了一个晚上,一个简易的WAP版记账系统就出炉了。登录/记账/查看最新记账,都有了。结果,很快发现一个比较严重的问题,发送数据不支持中文。 继续阅读 "Python Django WAP中文乱码" |
关于我![]() 搜索网站订阅到推荐文章友情链接系统管理 |


最新回复
21/11/2008 11:41
没什么大不了的 商业就是为了赚 钱 你可以不用百度 用百度总归要 付出点什么 忍受点什么
20/11/2008 17:02
同意楼上的!
20/11/2008 14:04
中国国情,我国特色,什么到中国 都会变味的
20/11/2008 13:45
有钱的企业排前面,很正确啊。有 钱的企业还不是在电视上出现的机 会高。医院什么 [...]
19/11/2008 17:46
反正我不喜欢百度的竞价方式!
19/11/2008 16:30
反垄断法只是限制微软用恶意手段 打击竞争对手,并不是限制微软必 须要20块钱卖自 [...]
19/11/2008 16:16
不是法律,那么反垄断法呢?
19/11/2008 15:30
写的好~~~ 世界在变 inte rnet 需要新的生活、思考方式