星期一, 二月 12, 2007

Django 学习笔记 - RequestContext

Context 常被翻译为“上下文”,可以在很多程序设计中见到他的身影。

不仅仅是 Django Template,几乎所有 Template Engine 的设计都是传递一个 Context 给 Template 进行渲染。这个 Context 就够成了模板所需的变量表。

Django Template 的特点就是简单,默认情况下调用 render_to_response 函数传递的第二个参数是一个简单 map 对象,会被包装成 django.template.Context 传递给模板使用。

其实很多场合我们需要默认在 Context 里面加入一些常用的东西,譬如把 request 对象传入 Context,把权限模型放入 Context 以便调用。为了避免每次硬编码,Django 提供了一个 Context 的子类,django.template.RequestContext。

在 settings 里面有一个名为 TEMPLATE_CONTEXT_PROCESSORS 的设置于 RequestContext 密切相关。默认的配置为:

("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n")


这些 Processors 都会被 RequestContext 顺序调用,往当前 Context 中放入一些预定义变量。譬如 auth 就会放置 user 这个变量,就是当前登录的用户对象。

RequestContext 作为 render_to_response 的第三个参数传递,必须将 request 作为参数传递给它,如下:

def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))

更多的信息请参考 Django 官方文档:
http://www.djangoproject.com/documentation/settings/#template-context-processors

星期五, 二月 09, 2007

Django 学习笔记 -Middleware

Django 的确可以做类似 Spring framework 里面 Interceptor 的操作,这在 Web 开发中相当不错。不过在 Django 里面这个不叫做 Interceptor 或者 Filter,他叫做 Middleware。

Middleware,多么庞大的概念,Java 开发着对这个此一定不陌生......,不过在 Django 的世界里,他就是 Interceptor,很简单。

Django 提供了很多默认的 Middleware 来作一些例如 URL 处理,Session 控制,和一些更基础的工作。Middleware 同时也构成了 Django 一个独特的插件机制。

Middleware 并不复杂,他主要就是可以让你在 HTTP 请求过来之
前和之后作一些处理。要实现 Middleware 并不需要继承任何类,脚本语言嘛,我们有 Duck Typing。

Middleware 里面有以下4个函数可用:

  1. process_request(self, request)
  2. process_view(self, request, view_func, view_args, view_kwargs)
  3. process_response(self, request, response)
  4. process_exception(self, request, exception)
看看函数名想必就知道做什么的了吧,写好 Middleware 之后随便放到哪里,只要在 settings.py 里面写上路径可以让 Python 找到就行了。

Middleware 的一些不足:
  • 全局应用,不能够针对某种 url pattern 应用自己的 middleware,不过可以自行扩展
  • 没有类似 Java Servlet 中 Filter Chain 的管理,完全是顺序应用 middleware,所以顺序很重要,因为有依赖。

Middleware 官方文档:
http://www.djangoproject.com/documentation/middleware/

星期二, 一月 30, 2007

重返 Blogger

这一个多月过得真是不容易,遭遇天灾,光缆断了,几乎没法写 Blogger 了,总算,现在应该恢复了 70% 了吧,好事情。

用 Django 做了一些东西,顺便学习了一下 Django,很有意思的一个框架。以前没有正经用 Python 做过东西,现在做下来感触还是很多的。先说说 Python 吧,个人观点。

随着 RoR 的兴起,动态语言的地位一下子上来了,越来越多的人学习脚本语言,不过似乎有一个问题。Python 很容易上手,的确不错,Python 依靠缩进来提高代码的可读性。不过也有一个似乎是脚本语言共有的问题,就算依靠缩进来提高代码的可读性,新手与老手写出来的代码也都可能是完全不同。很多 Java 的同行去尝试 RoR 了,很不错,很多新人也去玩,但是同样的东西写出来的代码质量可以相差很多。前些日子和 Martin 一起写过一些代码,pair 了一把,发现自己的水平比起来太差了,毕竟在 Python 上我算是个新手吧。

玩了玩 Django 和 TurboGears 两个 Python Web 框架,最后还是选择了 Django,有人说用 Django 的都是懒人,我承认我还是喜欢懒一点。TurboGears 整合了一群框架,可以自由替换前端和后端,没发觉有多少好玩的地方。我大致看了一遍 Django 的代码,觉得玩 Django 更有意思一点,扩展 Django 没多少难度,下阶段闲一点的时候我要整合一个新的模板引擎替换 Django Template。

可能最近一段时间都会用 Python 来做东西,就趁这个机会再细细研究一下这个语言本身了。

星期一, 一月 01, 2007

Ubuntu 下 resolv.conf 被替换的问题

用 Ubuntu 一段时间了,自从晚上使用无线网络之后就发现一个很恶心的问题,因为通过DHCP获取IP,所以经常重写我的resolv.conf,由于我自己配有bind9用作本地DNS缓存,所以经常要修改resolv.conf为我本地设置。Google 了一番,总算找到了解决方法,修改/etc/dhcp3/dhclient.conf,使用下面的语句为每次生产的resolv.conf准备默认的几台DNS地址:

prepend domain-name-servers 127.0.0.1;

星期二, 十二月 26, 2006

Django 学习笔记 - Apache2 + FastCGI

昨天开始学习Django站点的生产服务器(Production Server),尝试了一下lighttpd和Apache2,最后决定采用Apache2来搭建整个环境(其实lighttpd更为方便一些)。

虽然Apache2 + mod_python就可以跑Django站点服务,但是听说FastCGI有更优异的性能。

FastCGI applications are fast because they're persistent. There is no per-request startup and initialization overhead. This makes possible the development of applications which would otherwise be impractical within the CGI paradigm (e.g. a huge Perl script, or an application which requires a connection to one or more databases).
需要让Apache2支持FastCGI,就必须下载mod_fastcgi这个Apache模块。可以从http://www.fastcgi.com/站点下载,不过非Windows用户需要自行编译这个模块,其实也挺方便的。下面是我在 Ubuntu 下安装的例子:

apt-get install apache2-dev # 会安装Apache2开发相关的库
cd $mod_fastcgi_dir
apxs2 -o mod_fastcgi.so -c *.c # 编译
sudo apxs2 -i -a -n fastcgi mod_fastcgi.so # 安装到Apache2/modules里面去,同时会到apache配置里面加上一条加载语句

mod_fastcgi.so就这样完成了,下面需要配置你的Django站点。首先去下载 flup,然后写一个mysite.fcgi,这个在Django的站点上有介绍,里面需要指定Django应用的绝对路径。
#!/bin/bash

# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"

cd $PROJDIR
if [ -f $PIDFILE ]; then
kill `cat -- $PIDFILE`
rm -f -- $PIDFILE
fi

exec /usr/bin/env - \
PYTHONPATH="../python:.." \
./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE
这个文件搁在你的Django应用的根目录里面,改成可执行属性。然后你每次只需要执行这个文件就可以将Django以FastCGI方式启动出来了,启动后你是不能够直接访问的,因为不是走的Web方式。

下面我们看一下Apache相关的配置:
# Connect to FastCGI via a socket / named pipe.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock

<VirtualHost 12.34.56.78>
ServerName example.com
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /home/user/public_html/$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</virtualhost>
$1处我遇到了一个奇怪的问题,因为用的是 Ubuntu,没在其他平台试过,/$1会指向硬盘的/media物理路径,很奇怪,所以需要修改这个路径为Django的站点目录,即将DocumentRoot的地址再写一遍。

这样一来,整个Apache2+FastCGI就完成了,的确比较费力气。

星期四, 十二月 21, 2006

Django 学习笔记 - i18n 支持

最近再用 Django 做东西,顺便写点笔记做下记录。

今天折腾这个 Django 的 i18n 支持着实费了点功夫,主要是一开始没理解 Python 做 i18n 的原理导致。废话不多说了,使用 Django 的 i18n 支持还是相当的方便的。Django 的官方文档上讲的很详细了,但是篇幅过长,我也是硬着头皮看了几遍才搞明白,下面我就简单介绍一下最快捷的方法。

首先,从配置入手,settings.py 里面有一个 LANGUAGE_CODE属性,这里设置了网站默认的语言。由于settings.py里面的属性支持重写,所以从官方文档上可以得知,默认情况下已经启用i18n支持了,我们需要加入一些middleware来支持动态切换语言。

MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
注意顺序,LocaleMiddleware必须在SessionMiddleware下面,因为需要从Session里面获取一个语言类型,这些Django都有现成的了,很方便。

在urls.py里面配置一个i18n的辅助应用
(r'^i18n/', include('django.conf.urls.i18n')),
有了这个就可以自由的切换语言了,使用/i18n/setlang/?language=en这样的形式。

配置完成之后在项目目录底下建立一个locale目录,locale下子目录的样式有固定格式,如:
locale/<language>/LC_MESSAGES/
如果是中文,对应的目录就是
locale/zh_CN/LC_MESSAGES/
如果是英文,则应该是
locale/en/LC_MESSAGES/
以此类推。

为了在django里面使用i18n,po文件名必须为djang.po,编译过后必须为django.mo,那么翻译的内容就固定在po文件里了。一个典型的po文件类似一下样式:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-12-21 14:00+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Home"
msgstr "Home"

msgid "News"
msgstr "News"

格式相对比较简单,也是键值对的形式。如果是多行的话,需要使用msgstr ""的形式,首行不写东西,在后续的几行写文本,翻译出来的结果会由程序自动把文字组合到一起。

编写完的po文件需要编辑成二进制的mo文件才可以被django使用,django使用了gettext来实现翻译,所以mo格式也是gettext要求的。

在linux下使用msgfmt -o django.mo django.po即可完成转换过程,相当方便,windows下需要下载poEdit这个软件。

翻译工作都准备就绪了,接下来就是体现到模板上去了,首先加载i18n,在模板文件的头部加入{% load i18n %},下来对于需要i18n支持的字段使用{% trans 'Key' %},这里的Key就是msgid,很简单吧。

这里仅仅介绍了Django i18n的一个快速上手配置,更详细的内容请参考
http://www.djangoproject.com/documentation/i18n/

星期三, 十二月 20, 2006

回到 Ubuntu 的世界

总算下决心把笔记本上的 FreeBSD 删了,我的确没这个耐心去打各种各样的补丁来支持我的硬件了。Ubuntu 对桌面的支持已经非常强大了,安装很顺利,我的所有硬件都认出来了,包括无线网卡和声卡,这是一件很愉快的事情。Linux 有着强大的用户群和开发群,这点和 FreeBSD 的应用哲学还有点不同,我们房东雨同学说 FreeBSD 是“爱用不用”,呵呵,桌面环境是有点难用了。

看到众多老大们在玩 Beryl,的确够玄,于是立即将机器的 Ubuntu Dapper 升级到了 Ubuntu Edgy,可以不用重新安装就升级,输入命令 gksudo "update-manager -c -d",会显示一个升级选项,要下载645M数据,升级过程大概2小时左右,还不错。

升完级就装 Beryl 吧,就可以玩到很酷的 3D 桌面了,一点都不逊于 Vista 哦。

星期二, 十月 31, 2006

Nirvana Studio 有了自己的 Logo


Nirvana Studio 总算有了自己的 Logo,非常感谢 Tin 同学!

星期六, 十月 28, 2006

与 James Gosling 的合影



















比较遗憾的就是和 James Gosling 单独合影的照片一直都没有拿到!

星期四, 十月 26, 2006

常州发展史

4500万年前,人类祖先脊椎动物“中华曙猿”生活于溧阳上黄一带,比北非的“人类祖先”早800——1000万年。

6000余年前,原始居民聚居于戚墅堰圩墩村一带。

周灵王二十五年(公元前547年),吴王馀祭封季札于延陵,此为常州文字记载第一名称。

西汉高祖五年(公元前202年)改称毗陵。

三国时吴大帝嘉禾三后(公元234年)实行屯田,辖毗陵、武进(今丹徒)、云阳(今丹阳)3县农事。

西晋武帝太康二年(公元281年),废屯田典农校尉,改置毗陵郡,辖丹徒、曲阿、武进、延陵、毗陵、暨阳、无锡7县。自此至清代,常州均为郡、州、路、府所在地。

晋惠帝永兴元年(公元304年),因避东海王世子毗名讳,改称晋陵郡。

晋大兴元年(公元318年)侨置兰陵郡。

隋文帝开皇九年(公元589年),废晋陵郡,置常州,辖晋陵、无锡、义兴、江阴4县。

唐会昌四年(公元844年),升常州为望,列全国十望之一,辖5县同上(含武进县)。

昭宗景福元年(公元892年),建吴国,常州属吴,史称“三吴重镇”。

元世祖至元十四年(公元1277年),改置常州路,辖晋陵、武进2县和宜兴、无锡2州。

元惠宗至正十七年(公元1357年),改常州路为长春府,辖武进、无锡、宜兴、江阴4县。

明永乐七年(公元1409年),改长春府为常州府,辖县增靖江,计5县。

清雍正四年(公元1726年),常州府辖武进、阳湖、无锡、金匮、宜兴、荆溪、江阴、靖江8县,史称“八邑名都”。

1912年辛亥革命后废常州府,阳湖县并入武进县,城区一度称武进市,沿称常州,属江苏省。

1949年4月23日常州解放后,城乡分别设常州市和武进县,隶属于苏南行政区常州专区。

1953年,常州市升为省辖市。

1958年,镇江专区迁来常州,改称常州专区,辖常州、镇江2市和武进、金坛、溧阳、丹阳、扬中、句容、宜兴、溧水、高淳9县,隶属江苏省。

1983年1月,国务院批准江苏省实行市管县体制,3月起辖武进、金坛、溧阳3县。

2002年4月,国务院批准常州市建特大城市,撤县级武进市,设武进区,郊区更名为新北区;常州市辖金坛、溧阳二市和武进、新北、天宁、钟楼、戚墅堰五区。