浅析豆瓣的 Google Analytics 应用

2010年5月25日 没有评论

      关于这篇文章我觉得豆瓣在使用Google Analytics 自定义参数的使用上面还是值得借签的,除了频道流量分析,还有登陆用户跟踪也是一个亮点,对用户行为跟踪分析,不公能够实现全局跟踪,而且可以达到精确到单个用户.

      豆瓣 Google Analytics 代码加载模式

      豆瓣从今年开始也加入 Google Analytics 的统计阵营。让我们通过它加载的 Google Analytics 源码,简单分析一下它都是怎么应用的。

我们先从豆瓣的源码来看看它的Google Analytics统计代码

豆瓣 Google Analytics 代码

我们知道一般默认的 Google Analytics代码如下:

默认 Google Analytics 统计代码

      两相对比,我们就会发现豆瓣加载 ga.js 的方式与默认的方式有些不太一样,由于豆瓣并没有采用 https 加密访问,所以撇弃了默认的ga.js加载方式。

      默认的统计函数,pageTracker 也被豆瓣改成了 _ga ,这个只是名称定义上的区别,并没有什么实质的改变。豆瓣的主要应用是下面两个函数:

使用 _ga._addOrganic 识别非主流搜索引擎

       再来看豆瓣比默认 Google Analytics 代码增加的部分,那就是多了数个 _ga._addOrganic ,这是 Google Analytics 添加自定义搜索引擎的代码。尽管 Google Analytics 对于主流的搜索引擎都能自动识别,但毕竟能识别的是国外的主流搜索引擎,在国内,像搜狐的 Sogou,QQ 的 soso,网易的有道等搜索引擎,都不能被 Google Analytics 正确识别,而被当作推荐来源。这时候我们就可以利用_addOrganic 参数来识别这些非主流搜索引擎,如豆瓣的做法。

使用 _addIgnoredOrganic 忽略关键字

除了添加自定义搜索引擎,豆瓣在最后还添加了如下这些代码:

_ga._addIgnoredOrganic("豆瓣");
_ga._addIgnoredOrganic("douban
_ga._addIgnoredOrganic("豆瓣网
_ga._addIgnoredOrganic("www.douban.com");

这些代码用来把引号中的关键词从搜索引擎的关键词报告中排除,而当成直接点击量来源。

       为什么要这么做?因为一个知名的大网站,来自这些品牌词的搜索流量都非常大,常常是排在前几位的搜索关键词来源,而这通常是因为搜索引擎养成现在的人都懒得记网址,直接搜索品牌名来记住域名。这些品牌词对于网站的关键词来源分析并没有很直接的帮助,所以在来自品牌词的流量很大的情况下,可以直接把这些关键词识别成直接点击量来源。

关于自定义 Google Analytics 搜索引擎和排除特定关键词为直接点击量来源的语法,可以参考 Google Code 上关于这方面的详细介绍

通过 _setVar 识别用户

当我们登录豆瓣后,再来分析豆瓣的源码,会发现多了一个ga._setVar(”xxxx”)的 Google Analytics 参数。

豆瓣使用 Google Analytics 的._setVar参数来跟踪登录用户行为

      _setVar() 函数是 Google Analytics 的用户定义函数,主要用于对特定来源的用户行为进行分类,例如可以对登录浏览的用户设置一个数值,然后在 Google Analytics 后台的访问者/用户定义 中查看其浏览属性。

Google Analytics 访问者/用户定义报告

      分析豆瓣的源码可以知道,豆瓣对每一个登录后的用户,都赋以一个专门的 id 值,这样可以在用户定义报告里,看到整体的登录用户访问行为,乃至每个登录用户的浏览行为。通过这样设定后,豆瓣便可以轻易获取高忠诚度访问用户的访问行为。关于_setVar()的更多说明,请参阅 Google Analytics的技术文档

      如何根据访问者在我的网站上访问的页面或在表单上做出的响应对其进行分类?在 Google Analytics 官方的帮助文件,也给出了另外一个应用案例

       值得注意的是,原来在设置 _setVar() 函数的时候,整个网站的跳出率会出现重大的偏差,不过在最近的google analytics官方博客,指出该bug已经修正,客户在进行这方面设置的时候,还是要注意对比前后数据是否有重大偏差。

通过 _trackPageview 区分不同类型的评论

豆瓣上的书评,影评和乐评可以说是豆瓣网站的核心价值所在。一般评论的URL格式如下:

豆瓣上单条评论的URL

当我们查看该页面的网页源代码时,会发现有趣的现象:

豆瓣单条评论页的 Google Analytics 代码

      我们知道,一般 Google Analytics 的_trackPageview() 括弧中的参数是留空的, Google Analytics 会自动捕获网址的 URL 参数,如果在 _trackPageview()括弧中输入特定的数值,那么在 Google Analytics 的报表中,URL 将是我们指定的参数,而不再是我们在地址栏看到的 URL。

      如上面的例子,我们在 Google Analytics 中看到的URL将是/book/review/1946018/,而不再是我们在浏览器地址栏看到的/review/1946018/

      当所在频道是电影或者音乐时,_trackPageview() 中的参数将根据所在频道的属性,变为/movie/xxxxx 或者 /music/xxxxx的数值。

      豆瓣通过对的参数进行重新指定,主要有以下的好处:

        保证了用户和搜索引擎看到的 URL 比较简短,达到 URL 对用户友好和对搜索引擎友好的目的;而在 Google Analytics 报告中,通过 内容/内容细目/ 报告,又能了解到各个频道总的浏览情况。

      在GA的内容细目报告中,将会多出 /book/ /music/ /movie/ 这样的文件夹来,总而获得各个频道的合计浏览数据。

      而如果只是使用默认 _trackPageview(),你将只能得到所有评论页面的浏览数据,而无法得到细分的各个频道的浏览数据。

关于_trackPageview()的具体的使用方法可参照 Google Code 的说明

      注意事项:使用 _trackPageview() 参数重新指定 URL 之后,网站覆盖图的数据将受到影响。可参阅 Google Analytics 的官方帮助文件

      除了豆瓣使用 _trackPageview() 来对URL进行重写,大众点评网也采用了类似的做法(应该是比豆瓣更早采用。。。因为是我在点评网任职时候实验的做法;那时候豆瓣还没有使用 Google Analytis 统计代码,呵呵),有兴趣的同学可以自己去研究点评的 Google Analytis 代码。

原文: http://xiaolin0199.javaeye.com/blog/587390

分类: 其他 标签:

MySQLdb for Python使用指南/Python的数据库操作

2010年5月25日 没有评论

       注意一点就是进行数据ADU操作时,要conn.commit()进行提交,不然数据在数据库有过逗留,但并未最后对数据进行实质的ADU.

      可以从这里获得MySQLdb这个库http://sourceforge.net/projects/mysql-python
        如果你不确定你的python环境里有没有这个库,那就打开python shell,输入 import MySQLdb,如果返回错误信息,那就表示你的机器上没有,赶紧去下载一个.我的机器是win xp,所以我下载了win环境下的exe那个,直接双击完成安装.

在介绍具体的操作前,先花点时间来说说一个程序怎么和数据库进行交互
1.和数据库建立连接
2.执行sql语句,接收返回值
3.关闭数据库连接
使用MySQLdb也要遵循上面的几步.让我们一步步的进行.

0.引入MySQLdb库
import MySQLdb

1.和数据库建立连接
conn=MySQLdb.connect(host="localhost",user="root",passwd="sa",db="mytable")
提供的connect方法用来和数据库建立连接,接收数个参数,返回连接对象.

比较常用的参数包括
host:数据库主机名.默认是用本地主机.
user:数据库登陆名.默认是当前用户.
passwd:数据库登陆的秘密.默认为空.
db:要使用的数据库名.没有默认值.
port:MySQL服务使用的TCP端口.默认是3306.
更多关于参数的信息可以查这里
http://mysql-python.sourceforge.net/MySQLdb.html

然后,这个连接对象也提供了对事务操作的支持,标准的方法
commit() 提交
rollback() 回滚

2.执行sql语句和接收返回值
cursor=conn.cursor()
n=cursor.execute(sql,param)
首先,我们用使用连接对象获得一个cursor对象,接下来,我们会使用cursor提供的方法来进行工作.这些方法包括两大类:1.执行命令,2.接收返回值

cursor用来执行命令的方法:
callproc(self, procname, args):用来执行存储过程,接收的参数为存储过程名和参数列表,返回值为受影响的行数
execute(self, query, args):执行单条sql语句,接收的参数为sql语句本身和使用的参数列表,返回值为受影响的行数
executemany(self, query, args):执行单挑sql语句,但是重复执行参数列表里的参数,返回值为受影响的行数
nextset(self):移动到下一个结果集

cursor用来接收返回值的方法:
fetchall(self):接收全部的返回结果行.
fetchmany(self, size=None):接收size条返回结果行.如果size的值大于返回的结果行的数量,则会返回cursor.arraysize条数据.
fetchone(self):返回一条结果行.
scroll(self, value, mode=’relative’):移动指针到某一行.如果mode=’relative’,则表示从当前所在行移动value条,如果 mode=’absolute’,则表示从结果集的第一行移动value条.

下面的代码是一个完整的例子.
#使用sql语句,这里要接收的参数都用%s占位符.要注意的是,无论你要插入的数据是什么类型,占位符永远都要用%s
sql="insert into cdinfo values(%s,%s,%s,%s,%s)"
#param应该为tuple或者list
param=(title,singer,imgurl,url,alpha)
#执行,如果成功,n的值为1
n=cursor.execute(sql,param)

#再来执行一个查询的操作
cursor.execute("select * from cdinfo")
#我们使用了fetchall这个方法.这样,cds里保存的将会是查询返回的全部结果.每条结果都是一个tuple类型的数据,这些tuple组成了一个tuple
cds=cursor.fetchall()
#因为是tuple,所以可以这样使用结果集
print cds[0][3]
#或者直接显示出来,看看结果集的真实样子
print cds

#如果需要批量的插入数据,就这样做
sql="insert into cdinfo values(0,%s,%s,%s,%s,%s)"
#每个值的集合为一个tuple,整个参数集组成一个tuple,或者list
param=((title,singer,imgurl,url,alpha),(title2,singer2,imgurl2,url2,alpha2))
#使用executemany方法来批量的插入数据.这真是一个很酷的方法!
n=cursor.executemany(sql,param)

需要注意的是(或者说是我感到奇怪的是),在执行完插入或删除或修改操作后,需要调用一下conn.commit()方法进行提交.这样,数据才会真正保 存在数据库中.我不清楚是否是我的mysql设置问题,总之,今天我在一开始使用的时候,如果不用commit,那数据就不会保留在数据库中,但是,数据 确实在数据库呆过.因为自动编号进行了累积,而且返回的受影响的行数并不为0.

3.关闭数据库连接
需要分别的关闭指针对象和连接对象.他们有名字相同的方法
cursor.close()
conn.close()

三步完成,基本的数据库操作就是这样了.下面是两个有用的连接
MySQLdb用户指南: http://mysql-python.sourceforge.net/MySQLdb.html
MySQLdb文档: http://mysql-python.sourceforge.net/MySQLdb-1.2.2/public/MySQLdb-module.html

引用: http://xiaolin0199.javaeye.com/blog/585574

分类: 其他 标签:

PHP和Python/Ruby的运行机制的本质区别

2010年5月24日 没有评论

       刚接触CakePHP是刚进公司的时候,刚进来接手公司项目,也是第一次接触CakePHP,开始感觉"很过隐",也确实感受到了Rails的力量,但随着对项目的深入研究,质疑也开始越来越强烈,CakePHP的诟病也越来越明显。也确实一个稍大一点的项目如果用一个通用框架的话难免会出现顾此失彼的问题,前段时间接触了另外一个框架DooPHP,感觉这个框架的设计理念有很多可以借签的地方。因为这段时间精力有限,想尽快把Python拿下来,等有时间了再去写些DooPHP的东西吧。

      PHP和Python/Ruby的运行机制有一个本质区别:PHP是每次HTTP请求过来以后,初始化全部资源(例如创建数据库链接、加载系统类库,创建缓存等等),处理完毕,释放全部资源,这不像Python/Ruby之类带有GC的脚本语言,Python/Ruby是初次启动的时候初始化资源,随后的请求就不必再次初始化资源了。

这种机制的差异带来的区别就是:

1、PHP极难出现严重的内存泄露问题,随便你代码写的多烂,反正每个请求一执行完毕,所有资源统统释放光。而Python/Ruby则需要依赖GC来回收内存,因此稍有不慎,还是会出现GC无法释放的内存泄露问题。

2、PHP每次请求都要初始化资源,这个开销非常大。所以尽管PHP解析器本身的运行速度是极快的,但是一旦使用复杂的PHP框架,那么由于需要每次请求的时候初始化整个框架,性能的下降非常厉害,你用一个很复杂的PHP框架的结果就是整体性能被Ruby远远甩开。这也是为什么PHP社区这么多年来,并不怎么倾向于使用框架的原因之一。

3、由于PHP这种每请求初始化资源的机制,也造成了PHP添加跨请求的高级特性相当困难,这是PHP本身一个很大的限制,但是反过来说,正是这种限制使得PHP始终保持在一个比较简单的web语言上面,而正是这一点才是PHP得以成为互联网第一Web编程语言的原因,因此也未必就不好。

总之,PHP和Ruby的差异还是很大的,不适合放在一起比较,其实应该比较的是Ruby和Python才对。

      所以我觉得Rails这种框架性做法被PHP跟风以后,其实是把PHP带上了邪路,所以不如说是Rails在误导PHP的发展。顺便多说一句:DHH在编写basecamp之前,一直是用PHP的,并且自己还写了一个PHP的快速开发框架,他改用ruby以后,把当初自己写的PHP框架也移植过来了,这个框架实际上是Rails最初的原型。那么为什么DHH当初不直接基于PHP做Rails呢?非要改用ruby以后,才发表rails呢?你看看PHP这种运行机制就知道了,PHP做复杂的web开发框架并不是一条光明的道路。

引用参考:http://hanssonlan.javaeye.com/blog/403496

分类: 其他 标签:

XA™的日记 豆瓣的架构

2010年5月20日 没有评论

        豆瓣是一个值得让人敬佩的网站,国内为数不多的大型网站中,就技术创新和分享来讲,豆瓣做的很不错,我一直比较关注豆瓣.这是一篇言谈手记类文章,豆瓣是一个Python写的WEB2.0网站,很多关于Python以及网站架构方面的知识值得见识,对于新手,Python来说.

关键字包括:nginx,lighttpd,quixote,Memcached,mogile FS,Mako,Gentoo Linux,Xapian,spread

ps:窃以为第一段关于语言的采访,相当[csdn]化

      你要是愿意,就买一枝三块钱的玫瑰,送给我吧,这城市也是怪让人伤心的,我想死心塌地的爱上你”

     这是一个叫钟童茜的歌手的歌,我在豆瓣网站发现有人评论,才知道了这首有些凄凉的歌曲。你几乎不可能从百度的最流行的mp3的列表中找到它,因为它不是那么有名,也许是这个原因,引发了我采访豆瓣的愿望。接受我采访的是,豆瓣网站的技术总监洪强宁先生和产品经理张贝宁女士。

本刊记者:好,现在开始,豆瓣是一个非常著名的Web2.0网站,你们的开发语言选择的是Python,我想问的是,为什么选择Python?

洪强宁:我们选择Python的理由是它是动态语言,具有动态语言的优点,比如开发特别迅速。我们做的是一个Web2.0的网站,这种网站的特点就是always beta,用户的需求在随时发生变化,我们也不断发现新的价值。所以网站的结构和程序会不断变化,如果用Java做,你的开发量比较大,你就难以做出迅速地改变。Python的特点就是开发迅速,你可以在一两个小时,就做出一个功能。或者说已??上线了,用户反映需要某一功能,也可以比较快地做出来。

本刊记者:这就是TDD,敏捷开发的思路,和传统的方式有些不同。但是会有另一方面的问题,Python的程序员好找吗?在国内会Python的要比会Java程序员少的多。

洪强宁:对,确实是。在中国用Python的人确实不多,也给我们寻找开发任何人员带来困难。不过从另一方面说,也有好处,因为没有一个学校去教Python,会Python的人都是自己学的,也就是说他知道自己需要什么技术,而且能够通过自学掌握它,包括Python的资料中文比较少,需要学习者接触第一手资料,这都使得Python程序员的平均水平,要比使用其他热门语言的平均水平要高。另一方面Python也越来越流行,在国外比较流行的动态语言有Perl,和Python,现在Python已经超过了Perl。

本刊记者:不过,在Web开发这方面有许多选择,比如,Java,.NET,和PHP,在这个格局里Python还是比较弱势。

洪强宁:对,当然,它是新兴语言。在未来,我相信,至少在在Web2.0网站开发方面,它会有自己的一个位置。

本刊记者:还有问一个问题,Python与Perl比较怎么样?因为Python的面向对象的特性好一些,代码看起来更容易理解一些吧,我以前是用 Perl写程序的,觉得Perl的程序代码看起来比较乱。

洪强宁:对,Perl 是write once风格的,一个人写完了,过一段时间,可能自己都不能看懂,它确实很强大,但比较适合当作个人工具使用,不太适合团队的开发。Python的哲学是解决问题的最好方式只有一种,这样同样的功能,每个人写出来的程序样子应该差不太多,比较易于理解,更适合团队开发。

本刊记者:还有一个问题,,有一种说法,认为Python比较慢,在性能方面会不会有问题?

洪强宁:这个问题可以分两个方面说,首先,说Python慢,这是和编译语言比,比如与C,C++,Java比,在动态语言中,它并不慢,它比Ruby要快,它和Perl性能相当。如果选择动态语言的话,Python并不是很慢。另一方面,如果做网站开发,语言的不是速度的瓶颈,比如我把我们现在用Python写的程序全部用C写,程序当然会快一点,但是改变不是很大。Web网站一般会有很多对IO的操作,比如对数据库的访问,对硬盘的访问响应用户的请求,80%,90%你的时间都花在IO上,语言的速度,相对而言,不是那么重要。也可以这样说,网站的性能主要取决于架构设计的是否合理。因为网站需要响应大量的并发的请求,如果你的设计的不好,即使你用C写的,也可能无法应付。所以更多的考虑是在架构设计上,要使架构体系不会产生速度瓶颈。

本刊记者:那您能简要地介绍一下豆瓣的架构吗?

洪强宁:关于豆瓣的系统架构图,首先我们在Web server上做个划分,把网站内容分为动态内容和静态内容。在豆瓣上所有的html都是动态内容,图片都是静态内容。分成两个Web 服务可以做不同的调优。 对动态内容,我们用的是nginx和lighttpd的混合,nginx做负载的平衡,lighttpd通过 SCGi 与application server相连,application server是基于 quixote这个框架写的。

application server拿到用户的请求,分析用户的url,并且利用外部的资源,比如数据库,组合成一个html,返回。从数据库存取会比较慢,数据库有大量的IO,我们使用cache,我们使用的是Memcached,这是一个分布式的内存的cache,比如你可以用很多机器,每个机器有两个G的内存,我们自己开发了client端来使用它,另外如果用户有搜索请求,我们会用搜索引擎。Xapian是一个C++写的开源的搜索引擎,我们通过Web service去访问它。其他,我们还提供了另外的Web service接口响应用户的请求,比如要访问某个文件。spread是我们最近加了一部分,用户有的请求可以采用这样的异步服务。

数据库是这样的,两个MySQL做成一对,一个master ,一个 slave,根据应用划分,使得load不会太高。这个图上??的是两对,实际上有三对。还有一个slave,一方面作为备份,一方面用作数据挖掘,因为不能对线上的数据做直接操作。

对于静态部分,我们也是用nginx,你注意到豆瓣现在有日记的贴图功能系统,用户可能上传很多图片,我们采用的方案是用了mogile FS ,这是一个分布式的文件系统,同时可以做备份,保持高可用性,可以提高很大的IO。

关于application server,它都是用Python写的。我们是用的MVC方式,Controller我们用的是quixote ,它接受用户的请求,根据这个URL去找到Model的某个具体的函数来执行,它是一个dispatcher,当中会判断用户的权限等。然后再传给View,View根据模版进行渲染,形成网页。View的模版,我们以前是用的是PTL,PTL很高效,最近引用了mako,这是一个比较现代的开源的模版,用它写出的代码比较好维护,比PTL好维护一些.。同时,在使用mako的同时,我们的工程师做了很多加速的工作,现在mako的代码有很多是豆瓣的人写的。

你如果注意过Python的Web开发框架的话,你会发现Python的有三个比较著名的框架,Django,Pylons,TurboGears,Pylons默认的模版就是Mako。

下面的就是Model,业务模块,核心是类是User,因为Web2.0是以人为本,我们肯定会有一个User。只有人也做不了事情,还要有物。豆瓣的物,就是Subject,比如书,比如评论,比如小组等。

与数据库进行链接,我们一个很轻量级的与数据库进行链接,这也是一个开源项目,SQL Farm Manager。这个Web service,豆瓣中有很多用的都是Web service。

本刊记者:好,还想问您一个问题,Web2.0会不会也在架构设计中也有所体现呢 ?

洪强宁: Web2.0用户的反复的操作非常多,你需要一个非常流畅的体现。这需要一些技术来实现,比如Ajax;豆瓣花了很多钱很多精力,来提高性能,比如买好的机器,使用Gentoo Linux,为什么使用Gentoo Linux,因为它方便调优。还有,大量的使用cache。在数据库调优方面,我们也花了很大的精力。

另一方面,Web 2,0是用户提供数据的,用户有很多写操作。这样很多1.0优化方法在2.0中行不通。豆瓣在数据库上用的是分库的方式。除此之外我们还尝试了一些其他的方法。

本刊记者:我现在想问张贝宁一个问题,您能否谈一下Web2.0社区网站和传统的社区网站的区别?比如天涯论坛,和豆瓣的区别。

张贝宁:先说一下Web 2.0 的概念,传统网站,用户到这些网站,只是看信息,这些信息是怎么来的呢,比如像Google,它是抓来的,或者像新浪这样的门户网站,是用户给你编好的。你到这样的网站,只是获取信息,你不能创造信息,也不能决定它放的位置。按照业界的理解,Web 2.0相对于Web 1.0,它是以用户为中心的,或者说是以用户创造内容为主,并且可以决定展现方式。你刚才说的传统的社区,在某种程度上,也可以说是2.0的,因为它也由用户提供内容。不过早期的BBS,网站以内容作分类,比如体育,军事,文学等。用户不能形成自己的分类。在豆瓣,用户可以对任何一个话题进行讨论,这完全是用户自主的。这还只是关系到豆瓣的小组的功能,如果拿天涯论坛和豆瓣做比较的话,豆瓣与天涯这样的BBS不同还在于,它首先有一个物的概念,比如书,音乐,和电影。

本刊记者:我也发现了这点。这样的组织方式,给人的感觉会非常不同。比如我们要查找对余华的小说《活着》的评论,在豆瓣就比较容易找到认真,有质量的评论。而在传统的BBS上,你只能用查找的方式,搜索“活着”这个词,找出的东西,也可能还不是谈论《活着》这本小说的,而只是其中的文本包含了“活着”这个词,而且有很多无意义的吵架帖。豆瓣的组织方式,让人感觉很严肃,雅气。不过,我也发现了一个或许有些不便的地方,比如,我要在讨论德里达的小组回帖,在一般的BBS可以匿名,或具有一个ID就行了,但在豆瓣,我要首先参加德里达这个小组。

张贝宁:对,是这样的。豆瓣更关心的是人群,就是对同一话题和事物有兴趣的人群,而不是帖子,这与传统的BBS确实有一些区别。

本刊记者:好,就到这里。谢谢你们两位能够接受我的采访,分享你们的经验与思想。

原文:http://www.douban.com/note/29557381/

分类: 其他 标签:

Django新手需要注意的10个要点

2010年5月20日 没有评论

      博猪很牛X,JavaEye很小气,想回个评都还要搞个什么测试,鬼地去,我推上见过JavaEye的人,感觉印象不好.

      接触django是从上个月开始,学习python时间也不长,但我经常在社区看看别人发表的文章,早上看到一篇不错的博客,却一直不能访问,最终从bing的缓存里找到,因为害怕丢失和忘掉,所以顺便翻译过来,放到这里,同时也分享给大家,贡献给各位django初学的朋友们,希望能有一些帮助:)

原文地址是:http://zeroandone.posterous.com/top-10-tips-to-a-new-django-developer

1,不要将项目名称包含在引用代码里

      比如你创建了一个名为"project"的项目,包含一个名为"app"的应用,那么如下代码是不好的:

Python代码 复制代码

from project.app.models import Author

      缺点在于:应用和项目变成了紧耦合,无法将应用轻易变得可重用。如果将来要换一个项目名称,那你可有得受了。

推荐的做法是:

Python代码 复制代码

from app.models import Author

请注意,你需要将项目的路径配置在PYTHONPATH中。

2,不要硬编码MEDIA_ROOT和TEMPLATE_DIRS

项目配置文件settings.py中不要使用如下代码:

Python代码 复制代码
  1. TEMPLATE_DIRS = ( "/home/html/project/templates",)   
  2. MEDIA_ROOT = "/home/html/project/appmedia/"

当你在部署到生产环境,或者迁移服务器的时候,就会发生问题。

推荐使用如下方式:

Python代码 复制代码

SITE_ROOT = os.path.realpath(os.path.dirname(__file__))   
MEDIA_ROOT = os.path.join(SITE_ROOT, ‘appmedia’)   
TEMPLATE_DIRS = ( os.path.join(SITE_ROOT, ‘templates’),)  

(也可以使用abspath,跟realpath的区别请参考http://rob.cogit8.org/blog/2009/May/05/django-and-relativity-updated/

3,不要将静态文件的路径硬编码在模板中

模板中链接CSS,javascript或图片的时候,不建议使用如下方式:

Html代码 复制代码

<link rel="stylesheet" type="text/css" href="/appmedia/amazing.css" />  
<script type="text/javascript" src="/appmedia/jquery.min.js"></script>  

      当你的项目需要将静态文件用其他服务器提供的时候,通常会是另外一个http地址,那么你就得把所有的/appmedia/替换成新的地址,做网站写代码已经够乏味的了。

没有后顾之忧的解决方法是使用{{ MEDIA_URL }}代替硬编码的路径:

Html代码 复制代码

<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}amazing.css" />  
<script type="text/javascript" src="{{ MEDIA_URL }}jquery.min.js"></script>

模板上下文变量怎么获取到呢?请使用RequestContext即可:

Python代码 复制代码

return render_to_response("app/template.html", {‘var’: ‘foo’},   
context_instance=RequestContext(request))

从RequestContext里还可以获取到当前用户等信息,更详细的介绍请参考:
http://www.b-list.org/weblog/2006/jun/14/django-tips-template-context-processors/

4,不要将业务逻辑代码写到视图里

       不要迷惑,虽然你可能看过很多书和例子,它们把逻辑都写在了views.py里,但请你别这么做。因为这样不利于单元测试,不利于重用代码。

      那我的业务逻辑应该放哪里呢?推荐放到模型里或者单独建立一个辅助(helper)模块。

当然,从模型得到一个Author,获取Author列表的代码是可以放到视图里面的。

5,部署时别忘记将DEBUG设置成False

我们常常忘记在部署时禁用DEBUG,有很多种方法自动来处理这个配置:

Python代码 复制代码

import socket     
if socket.gethostname() == ‘productionserver.com’:   
    DEBUG = False  
else:   
    DEBUG = True   

此方法请参考:http://nicksergeant.com/blog/django/automatically-setting-debug-your-django-app-based-server-hostname

另一种途径是使用不同的配置文件:

Python代码 复制代码

#文件名:settings_debuy.py   
#包含调试模式的配置信息   
#使用python manage.py runserver settings=settings_debug.py来运行项目      
from settings import *      
DEBUG = True    
#还可以配置更多在调试时使用的变量:)  

此方法请参考:http://blog.dpeepul.com/2009/07/02/from-now-you-will-never-forget-to-put-debug-true-in-django-production-environment/

6,只加载一次自定义的模板标签

当需要使用自定义或者第三方的模板标签和模板过滤器时,通常要在模板中使用:

Python代码 复制代码
{% load template_tags %}

实际情况是,需要在所有用到自定义模板标签和模板过滤器的模板中都使用上面的代码,这样就不DRY了。

Python代码 复制代码

from django import template     
template.add_to_builtins(‘app.templatetags.custom_tag_module’)  

请将以上代码放到项目启动时能加载的模块中(settings.py, urls.py, models.py等)即可。

上面代码的作用是在项目启动时就把自定义模板标签或过滤器加载进来,模板中任何一个地方都可以使用它们,而不需要{% load template_tags %}。

7,合理配置和使用URL

不要将URL全都配置在一个urls.py文件中,比如:

Python代码 复制代码

urlpatterns = patterns(,   
  url(r‘^askalumini/question/$’,‘…..registerInstitution’,name=‘iregister’),   
  url(r‘^askalumin/answer/$’,‘someview…..’,name=‘newmemberurl’),   
  url(r‘^institution/member/$’,‘someview…..’,name="dashboardurl"),   
  url(r‘^institution/faculty/$’,‘editInstitute’,name="editinstituteurl"),   
url(r‘^memeber/editprofile/$’,‘editProfile’,name="editprofileurl"),   
  url(r‘^member/changepassword/$’,‘changePassword’,name="changepasswordurl"),   
  url(r‘^member/forgotpassword/$’,‘forgotPassword’,name="forgotpasswordurl"),   
  url(r‘^member/changepicture/$’,‘changePicture’,name="changepictureurl"),   
  url(r‘^member/logout/$’,‘memeberlogout’,name="logouturl"), ,   
)  

建议的方式是将各应用的URL配置在各自的urls.py中,这样可以使应用更容易重复使用到不同项目里:

Python代码 复制代码
  1. urlpatterns = patterns(,   
  2.   (r‘^$’, include(‘institution.urls’)),   
  3.   (r‘^institution/’, include(‘institution.urls’)),   
  4.   (r‘^askalumini/’, include(‘askalumini.urls’)),   
  5.   (r‘^member/’, include(‘member.urls’)),   
  6. )  

如下是应用askalumini的urls.py:

Python代码 复制代码
  1. urlpatterns = patterns(‘askalumini.views’,   
  2.   url(r‘^$’,‘askHome’,name=‘askaluminiurl’),   
  3.   url(r‘^questions/(?P<questionno>\d+)/$’,‘displayQuestion’,name=‘askquestiondisplay’),   
  4.   url(r‘^askquestions/$’,‘askQuestion’,name=‘askquestionurl’),   
  5.   url(r‘^postcomment/$’,‘postComment’,name="askquestioncomment")   
  6. )  

      刚才提到静态文件路径不要硬编码,url的处理方式也尽量不要硬编码,否则当你更改一个地址时会牵涉到多处的修改,可以使用一些url函数来处理。

在/project/askalumini/urls.py中,为每一个url定义了name,它可以帮助我们有效地在视图、模板和模型中处理url,而不是硬编码。

为保证名称的唯一,请遵照将url命名为<appname>/<somelabel>的习惯用法。

举例来说,在views.py文件中有如下代码:

Python代码 复制代码
  1. HttpResponseRedirect("/askalumini/questions/54")  

请改为:

Python代码 复制代码
  1. from django.core.urlresolvers import reverse   
  2. HttpResponseRedirect(reverse(‘askquestiondisplay’,kwargs={‘questionno’:q.id}))   

在模型中使用models.permalink装饰器来格式url:

Python代码 复制代码
  1. @models.permalink   
  2. def get_absolute_url(self):   
  3.     return (‘profileurl2’,(),{‘userid’: self.user.id})  

在模板中使用url标签代替硬编码:

Html代码 复制代码
  1. {% url askquestiondisplay 345 %}   
  2. <a href="{% url askquestiondisplay 345 %}"> Ask Question </a>   

8,调试

调试通常会借助一些第三方工具来获得更多的运行时信息。

一个请求执行了多少句SQL?花了多长时间?

调用的哪个模板?客户端设置了什么COOKIE?SESSION呢?。。。

你可以使用django-debug-toolbar查看上面甚至更多的信息:http://github.com/robhudson/django-debug-toolbar

另一个工具是Werkzeug debugger,它可以在错误页面打开python shell,让你更方便的跟踪错误信息,请访问:http://blog.dpeepul.com/2009/07/14/python-shell-right-on-the-django-error-page/ 获得更多信息。

还有pdb,一个强大的调试工具:http://ericholscher.com/blog/2008/aug/31/using-pdb-python-debugger-django-debugging-series-/

9,了解pinax备用

django最大的优点是代码重用,DRY,pinax就是这样一个平台,包含了许多可拿来直接使用的代码,比如openid,电子邮件验证等等。请访问:http://pinaxproject.com/

10,了解一些著名的第三方应用

1)数据库升级工具

什么是数据库升级工具?你运行了syncdb,运行了一年之后,对模型做了更改,添加了字段,删除了字段,要再运行syncdb吗?或者ALTER TABLE …?

django-evolutions可以帮你完成上面的事情,但它好像不够强壮:http://code.google.com/p/django-evolution/

South能很强壮地完成上面的事情,但是需要学学怎么用:http://south.aeracode.org/

2)模板系统

django自带的模板系统是可以替换的,并且各自有优缺点。

template-utils增强了模板的比较标签等功能 ,并提供其他的一些实用特性:http://django-template-utils.googlecode.com/svn/trunk/docs/

Jinja是一个完整的第三方模板系统,可以替换默认模板系统,它提供了许多优越的特性:http://jinja.pocoo.org/2/

3)第三方应用

django command extensions提供了很多实用的命令行功能:

shell_plus加载所有django模型

runserver_plus整合了Werkzeug调试工具

生成模型图表,你可以展示给你的老板

……

请参考:http://ericholscher.com/blog/2008/sep/12/screencast-django-command-extensions/

Sorl可以生成缩略图:http://code.google.com/p/sorl-thumbnail/

…………

—END—

另外,从原文的评论里也有不少发现:

原文:http://shinyzhu.javaeye.com/blog/593427

分类: 其他 标签:

Django资源大全

2010年5月20日 没有评论

     最近在扎腾Python,发现一个很好用的Django,设计理念确实很独到,特别是管理后台的自动生成和高度可定制化,确实很人性,省却了不少麻烦.不过,MTV设计模式倒是让习惯了MVC模式的PHPer比较有意外,原来除了Rails之外,还有也很好用的东西,哈~哈,都快成了转贴大神了.

以前整理的django资源列表,从我的wiki上转过来的。

要找django资源,官网的wiki也是一个不错的地方。

http://code.djangoproject.com/wiki/DjangoResources

资源

使用django搭建的站点

  • django官网 django官网本身使用django搭建,而其提供了代码。django官网的大多功能由整合的trac实现,所以网站的django代码没几行。
  • 海报网 据说这是目前流量最大的django站点。据我的了解,这个网站的流量也确实大的有些超乎想象,该网站应当有接近CSDN的流量。不过这个网站将大量的页面进行了静态化,如果以这个网站的标准来评价django的性能应当不够客观。
  • 好看簿 国内的另一个django站点,目前也有不错的流量。作为该网站的用户,我感觉网站的响应速度并不怎么快。看来好看簿在服务器优化方面还需要更多的努力。

django的开源项目

  • pinax 这是我看到的最有价值的django开源项目。pinax可以看做是django的一个脚手架。她提供了快速开始一个新django项目的方法,同时对大量第三方app的使用方法进行了演示。django的app质量参差不齐,如果你想挑选app,那你可以看看pinax里都集成了哪些app。pinax 里集成了的app通常都不至于太烂。此外pinax自身也带了一些有用的app,比如blog等。
    如果你想以最快的速度了解pinax,可以去 http://cloud27.com/ 看看。这是一个用pinax搭建的SNS网站。
  • Satchmo 网店系统。看她的介绍,似乎已经有不少人在用这东西了。
  • LFS(Lightning Fast Shop) 网店系统,就Demo来看似乎是倾向于房屋交易平台。陆陆续续的也有部分商业网站开始使用该系统了,比如这个
  • reviewboard 非常有前途的一个code review工具。最开始是VMware在用,来后给开源了。

django的可重用app

CMS

Forum

调试

  • django-debug-toolbar 为django站点增加调试功能,支持查看django生成的sql语句,及sql的执行时间等,功能强大。不过由于该组件使用了jquery,似乎会使用部分使用了jquery的站点无法正常工作。
  • django-db-log 将django的异常保存到数据库。
  • django-logging 增加sql日志。直接在站点的网页上查看当前页面所使用sql语句以及执行时间。功能比django-debug-toolbar要弱不少,不过要是django-debug-toolbar把你的页面毁了,那就试试这个吧。

数据库升级

在项目开发过程中表结构的变动总是难免,django目前还不支持表结构的自动更新,不过相关的第三方app倒不少。这些app各有各的特色,具体如何选择就要看个人的喜好了。

  • SchemaEvolution 介绍django数据库升级的wiki页面,相关的app都可以在这个页面找到。

未分类

  • django-registration 注册功能,支持帐户的邮件激活。
  • django-tagging 为站点增加tagging功能
  • django-voting 投票功能
  • django-ajax-validation 使用ajax方式对表单进行校验,需要jquery的支持。这个组件只能校验,如果需要增加ajax提交表单的功能,还需要自己手动做些修改。
  • django-announcements 发送站内公告,该公告只显示一次。可以设置公共的发送对象(所有人,指定用户,登陆用户)。
  • django-avatar 为用户增加设置个人头像的功能。支持 http://www.gravatar.com/ 和用户上传头像。
  • django-dbtemplates 将django的template保存在数据库,并通过cache来加速template的加载。这样可以很方便的通过admin来编辑template。我想这东西应当可以用来实现一些简单的CMS功能,不过似乎用处不是太大。
  • django-microblogging 类似Twitter的微型博客
  • django-notification 消息分发组件,用来实现类似好友最新动态的功能。
  • django-pagination 一组翻页相关的utils,包括用于实现翻页的tag等。
  • django-robots 通过django的admin来管理robots.txt。不过我觉得robots.txt这东西为什么还需要用admin来管理,还不如直接编辑来的方便。
  • django-messages 实现站内消息的功能。目前该组件的功能的功能还比较弱,虽然作者在进行重构,但似乎进展缓慢。如果有需要我可能会自行对该组件进行一些增强。
  • django-threadedcomments 评论组件,可以给任何的models增加评论功能。
  • django-extensions 一些全局的 management extensions。其中包括create_app的增强,使用werkzeug做开发服务器等功能。
  • django-uni-form 以div方式渲染forms
  • django-timezones 时区设置组件,允许用户设置自己所在的时区。
  • django-bookmarks 书签管理组件
  • django-email-confirmation 在用户设置邮件地址后,给用户的邮箱发送一封确认邮件。用户点击邮件里的link来确认邮件地址的有效性。
  • django-mailer 邮件发送的增强组件,会在邮件发送失败时记录失败日志。
  • django-friends 朋友组件,支持邀请用户成为好友等。
  • django-locations 似乎是一个基于地区的社交网络,需要yaohoo map的支持。
  • django-oembed 方面媒体(视频等)内容嵌入,自动将媒体的连接转换成正确的html代码。
  • django-swaps 易物平台,比如用PSP换NDS啥的。
  • django-wikiapp wiki组件,支持多种wiki语法。不过目前该组件的功能还是比较简单,比如不支持附件。
  • django-mptt 用于生成树形列表的app。如果你认为它会自动给你生成一个完整的树,那你就错了,她只是一组工具。我感觉这东西并不是太好用,是否有什么优点,暂时不太清楚。
  • django-photologue 图片管理,上传图片,缩略图显示等。
  • django-filebrowser django-admin的一个扩展,可以直接通过admin对服务器上的文件进行管理。我没用过这东西,不过看介绍,感觉非常棒。
  • goflow Django上的一个工作流引擎,设计灵感来源于OpenFlow。没用过这东西,对工作流也不太了解,所以也不知道这东西好不好。不过这似乎是django上唯一的一个工作流app。

原文:http://www.javaeye.com/topic/405150

分类: 其他 标签:

为 Python Server Pages 和 Oracle 构建快速 Web 开发环境

2010年5月17日 没有评论

       通过可靠的 Oracle 数据库 10g、可伸缩的 Apache Web 服务器以及直观的、面向对象的 Python 编程语言学习高级 Web 编程。

       各种在 Web 服务器和数据库之间充当中间层的服务器端技术使当今的开发人员获益匪浅,这些技术包括 JavaServer Pages (JSP)、Active Server Pages (ASP)、PHP 以及 PL/SQL Server Pages(如果您是一位 Oracle 开发人员)。                                                                           武汉百度推广

      我在 2003 年首次接触 Python 编程语言,并从那时起开始沉迷于这种语言的独特魅力及其简便的使用。它是一种高级语言,几乎类似于以纯英文编写,就好像编程人员对于伪代码的认识。Python 的动态本质使您能够编写最简明的代码来完成甚至最复杂的任务。

      在这篇文章中,我将简要介绍一种创建完整的 Python Server Pages/Oracle 数据库 10g 快速 Web 开发环境的简单方法。本文假设您没有在 Windows 或 Linux 系统上安装任何组件。(如果已安装,则可以相应地跳过某些步骤。)所有提到的组件都可免费下载,并且不需要任何许可费用。

Python 和 Python Server Pages 的背景

      Python 提供了强大的自我检测功能、可动态键入、完全面向对象,并具有可扩展性以及平台独立性(Windows、Linux、Solaris、Mac OS、Nokia / S60、Pocket PC 等等)。它使您能够获得高生产率并以结果为导向,重在解决问题而非应对语言固有特性。Python 的可读性很强,非常易于维护(通过对代码样式提出特定要求)。我有许多实际上可以执行复杂任务的 Python 单行程序(有时是双行程序,如果包含导入语句),它们远比“hello-world”那样的程序功能强大。

      Python 最大的优势之一是其广泛的标准库,其中提供了可用于大多数编程任务的现成模块组(Python 编程人员称其为“带电池的策略”),包括文件 I/O、系统交互、联网、数据分析和操作、线程、监测、单元测试、自我检测、XML 处理等等。

      您将会着迷于利用 Python 获得的开发速度 — 最终可以让计算机理解而不是误解您的意图。此外,利用内置的文档字符串 (docstring) — 即内嵌的帮助字符串,其他编程人员可以快速理解您的类或函数的精髓。(从源代码创建文档轻而易举。)正是由于这些原因,Google 和 NASA 使用了大量的 Python,而 Microsoft 正在 .NET 平台上开发自己的 Python 版本,称为 IronPython。

      Python Server Pages (PSP) 之于 Python 正如 Java Server Pages 之于 Java。较之以常规 CGI 处理的页面,利用 PSP 呈现的页面的执行效果要好 50 倍。Mod_python 包含了许多专门的模块,使得 Web 开发更简单。

解决方案组件

      完整的 Web 开发环境至少必须包含三个基本组件:Web 服务器、数据库以及服务器端后端技术。此外还有一些功能要求,例如可靠性、可伸缩性以及互操作性。为了满足上述条件,我选择使用 Apache HTTP Server 2.0、Oracle 数据库 10g 快捷版 (XE) 以及 Python 2.4(带有 mod_python 和 cx_Oracle 模块)。(请阅读并找出选择这三项的原因。)

      不但 Linux 用户仍然无需键入太多内容,就是 Windows 用户也必定享受所有这些组件的简单安装方式(只需单击 Next)。我已经简化了安装过程,以利用可用的二进制文件。

Oracle 数据库 10g 快捷版

      2006 年 2 月,Oracle 推出了 Oracle 数据库快捷版的生产版。它是 Oracle 数据库 10g 第 2 版的小型入门级版本,其开发、部署以及分发完全免费。

      Oracle 数据库快捷版适用于 Windows 和 Linux 操作系统,是 PHP、Java 或 .NET 开发人员的首选。此外,利用大量可用的第三方模块和驱动程序,可以通过各种不同的编程语言(包括 Python)访问该数据库。                                                        武汉百度

       Oracle 数据库快捷版具有西欧与通用两种版本。前者只支持 LATIN1 字符,而后者的默认字符集为 AL32UTF8。通用版本还包括翻译为巴西葡萄牙文、中文(简体和繁体)、英文、法文、德文、意大利文、日文、韩文以及西班牙文的管理界面。没有人愿意仅限于使用 LATIN1,因此我建议安装并使用通用版。

安装并运行 Oracle 数据库快捷版

下载适用于 Windows 的 OracleXEUniv.exe 或适用于基于 RPM 的 Linux 版本的 oracle-xe-univ-10.2.0.1-1.0.i386.rpm。(Oracle 数据库快捷版也适用于 Debian,但这超出了本文档的讨论范围。)

在 Windows 平台上:

  1. 使用具有管理员权限的帐户登录 Windows。
  2. 如果系统之前已设置了 ORACLE_HOME 变量,请将其移除。
  3. 双击第一步中下载的安装可执行文件。
    图 1
  4. Oracle Database 10g Express Edition – Install Wizard 中,单击 Next
  5. License Agreement 窗口中,选择 I accept,然后单击 Next
    图 2
  6. Choose Installation Location 窗口弹出后,您可以接受默认目录,也可以通过单击 Browse 按钮选择所需的目标位置。完成该步骤后,单击 Next
  7. 如果系统提示输入端口号,您应当指定一个。Oracle 数据库快捷版的默认端口号是
    • 1521,用于 Oracle 数据库监听器
    • 2030,用于 Oracle Services for Microsoft Transaction Server
    • 8080,用于可通过 Web 浏览器访问的 XE 图形化管理界面
  8. 现在,需要为 SYSSYSTEM 数据库管理员帐户设置口令。在 Specify Database Passwords 窗口中,输入所需的口令并进行确认。单击 Next
  9. Summary 窗口将显示整个过程中设置的安装参数。如果您接受这些参数,则单击 Install 开始安装。
  10. 单击 Finish 完成安装过程。如果希望启动管理浏览器界面,请选择 Launch the Database homepage 选项。您已在 Windows 上成功安装了 Oracle 数据库快捷版。

在 Linux 平台上:

  1. 以 root 用户身份登录。
    图 3
  2. 将当前的路径更改为您在第一步中下载 RPM 安装程序的目录。
  3. 运行以下文件启动安装过程:
    # rpm -ivh oracle-xe-univ-10.2.0.1-1.0.i386.rpm

    (安装过程开始。)

  4. 现在,当系统提示运行以下命令时,需要为已安装的数据库设置参数:
    # /etc/init.d/oracle-xe configure
  5. 输入以下详细信息:
    • 用于 Oracle 数据库快捷版图形用户界面的 HTTP 端口(默认为 8080)
    • 用于 Oracle 数据库监听器的端口(默认为 1521)
    • 用于 SYSSYSTEM 管理数据库帐户的口令
    • 在系统重启后是否希望自动启动该数据库
  6. 您可以随时运行以下命令来重新配置数据库:
    # /etc/init.d/oracle-xe configure
  7. 要通过启动或停止数据库实例来对其进行控制,可使用随 XE 一起安装的菜单选项,或从命令行运行以下命令:
    # /etc/init.d/oracle-xe start

    # /etc/init.d/oracle-xe stop

现在,您可以通过在浏览器中打开 http://127.0.0.1:8080/apex/ 来登录 XE 的图形管理界面。(如果数据库是使用自定义参数配置的,则需相应地更改路径。)

安装 Apache HTTP Server 2.0

根据最新的统计数据,目前 Apache HTTP Server 至少部署在全球三分之二的 Web 服务器上。由于其甚至可以支持伸缩性最强的体系结构,所以它可用于各种系统平台,包括 Microsoft Windows 和 Linux。

然而,Apache 不仅仅是一个 Web 服务器。Apache Software Foundation 支持许多开放源代码的企业级产品,包括著名的 Struts 框架、Tomcat servlet container、Derby 数据库、Axis 平台、FOP 处理器以及 Xerces parser 等等,数不胜数。Apache HTTP Server 非常易于配置,并为各种服务器端配置提供了无与伦比的灵活性。此外,正如您所知,它还可充当 Oracle HTTP Server 的核心。

在 Windows 平台上:

  1. 以管理员身份登录并下载 MSI Installer apache_2.0.55-win32-x86-no_ssl.msi;双击该程序开始安装过程。
  2. 屏幕上将显示 Apache HTTP Server 2.0 – Installation Wizard。单击 Next 继续。
    图 4
  3. License Agreement 窗口中,选择 I accept the terms in the license agreement,并单击 Next
  4. 您将在 Read This First 窗口中看到一些 Apache HTTP Server 信息,单击 Next 继续。
  5. Server Information 对话框将出现。此时,需要输入以下信息:
    • Network Domain — 服务器目前所在或即将注册到的 DNS 域,对于完整的 DNS 名 py.oracle.com,只需输入 oracle.com 即可。
    • Server Name — 服务器的完整 DNS 名,不能像上面的 Network Domain 那样省略任何信息。
    • Administrator’s Email Address — 默认情况下,该电子邮件将与该服务器生成的错误消息一同显示给客户端。
    • 选择要为其安装 Apache Server 的帐户,可以是 for All Users(所有用户),也可以是 only for the Current User(仅当前用户)。(如果您不希望 Apache 损坏 Oracle 数据库快捷版的默认 HTTP 8080 端口,我建议您选择第一个更为方便的选项。)
      图 5
  6. 设置完这些参数后,请单击 Next
  7. 在下一个 Setup Type 窗口中,您需要选择是进行 Typical 还是 Custom 安装。除非您希望更改目标位置,否则使用 Typical 安装,这将跳过用于编译模块的标题和库。(在以后的步骤中将使用预编译的模块。)此时,我将 Apache 安装目录命名为 APACHE_HOME。单击 Next 继续。
  8. Ready to Install the Program 窗口显示后,单击 Install 启动安装过程。
  9. 单击 Finish 完成安装。

在 Linux 平台上(RPM 方法):

  1. 如果您的系统已经包含了 Apache HTTP Server,可以跳过这一部分。大多数 Linux 版本在默认情况下安装有 Apache,但您需要确保安装有 2.0.x 版。(使用 rpm -qa | grep apache 命令进行自我检测。)
  2. 下载 httpd-2.0.55-1.i386.rpm。
  3. 运行以下命令进行安装:
    # rpm -ivh httpd-2.0.55-1.i386.rpm

    APACHE_HOME 的默认位置可能根据 –prefix 参数而有所不同,一般为 /usr/local/apache2。)

  4. 从源过程进行安装在 http://httpd.apache.org/docs/2.0/install.html 上有述;如果您的版本无法处理 RPM,那么此处提供的内容将是不错的指导信息。

要检查 Apache HTTP Server 是否运行正常,请转至 http://127.0.0.1/ 并查看是否显示了默认欢迎页面。

但是,Apache 的配置不完整,您仍需要安装 Python 和 mod_python。请按照以下步骤,在您的操作系统上完成 Python 解释器的安装。

安装 Python

在 Windows 平台上:

  1. 转至 http://www.python.org/,并在 Quick Links 部分中找到指向 MSI 文件(名为 Windows Installer)的直接链接。(截至本文撰写之日,Python 的当前版本为 2.4.3)。将 python-2.4.3.msi 文件保存到计算机上。
  2. 以拥有管理权限的用户身份登录,双击下载的安装程序可执行文件。以下屏幕将出现,您需要选择是为所有用户还是当前登录用户安装 Python。选择所需的选项后,单击 Next
    图 6
  3. Select Destination Directory 窗口中,保留默认路径或将其更改为所需的目标位置,并单击 Next
  4. 此时,您可以启用或禁用要在系统上安装的特性。建议您保留所有这些项的默认状态,但是如果您决定只包含其中的一部分,则可以随意进行更改。选定所需特性后,单击 Next 开始安装。
    图 7
  5. 单击 Finish 完成安装。

在 Linux 平台上:

Python 的 Linux 安装完全取决于系统版本。此处有很多安装选择,如果您的系统不是太旧的话,则已经使用 Python 2.4 的几率比较大。请访问 http://www.python.org/download/linux/ 查看可用选择。

安装 mod_python

我们将使用 mod_python 将 Python 连接到 Apache HTTP Server,这是一个最初由 Gregory Trubetskoy 编写并大方赠与 Apache Software Foundation 的模块。该模块自 2000 年以来在互联网上就有提供,并在 2002 年成为 Apache 模块组的一部分。

Mod_python 使您能够访问许多低级 Apache 内部信息,并提供比其他基于 Apache 的服务器端解决方案(例如 mod_php 或 mod_perl)更为优异的灵活性。您不一定会使用这些内部信息,但由于我们关注的是快速 web 开发,因此将介绍它提供的完全针对 PSP 的高级接口。

通过 mod_python,您可以充分利用 Python 及其模块,编写能够以可重用模板形式进行缓存和包装的服务器页面。请注意,PSP 引擎是 mod_python 提供的众多解释器之一,但由于我们要将 Python 代码直接嵌入页面源代码,因此 PSP 是首选解决方案。

安装 mod_python

Windows 安装故障排除

在某些系统配置下,Apache 无法找到 Python 库和模块的路径。一个简单的变通方法是,更改运行 Apache 2 服务的帐户。

运行 services.msc 命令,并从可用服务列表中选择 Apache 2;右键单击并选择 Properties。在 Log On 选项卡上,设置 This account 选项,并为当前用户输入口令。按 OK 并重启该服务。

在 Windows 平台上:

  1. http://www.apache.org/dist/httpd/modpython/win/3.2.8/ 下载 mod_python-3.2.8.win32-py2.4.exe,并双击下载的可执行文件。
  2. 单击 Next 继续。
  3. Mod_python 安装程序将试图找到默认的 Python 2.4 解释器。要接受选择,再次单击 Next
  4. 要开始安装过程,按 Next 按钮。
  5. 安装结束后,安装程序将询问 Apache 2 的位置 (APACHE_HOME)。使用树形浏览器导航到正确的目录,并按 OK
  6. 单击 Finish 完成安装。

在 Linux 平台上:

  1. 该步骤需要编译模块。为此,从 http://www.apache.org/dist/httpd/modpython/ 下载 mod_python-3.2.8.tgz 文件,并将其置于 Linux 系统的 /tmp 目录中。
  2. 您需要将 mod_python 编译为动态共享对象 (DSO),以便在运行时由服务器进行加载。这使您无需重新编译 Apache 服务器即可对其进行编译。理想情况下,/tmp 目录下的 ./configure; make 应当足以编译该模块。根据系统配置,可能会出现需要手动指定 Apache、Python 和/或 Flex 位置的情况。如果遇到编译错误,请查阅官方 mod_python 安装指南
  3. 最后,需要安装已编译的模块。您需要以 root 身份进行安装。仍然在 /tmp 目录下,运行 $ make install 并等待直至该执行操作完成。

配置 Apache HTTP Server 处理 PSP

安装完 mod_python 之后,必须要让 Apache 知晓。为此,请打开 APACHE_HOME/conf/httpd.conf 进行编辑(请查阅系统文档,以了解 httpd.conf 在 Linux 上的默认位置),并将以下代码行追加到末尾:

LoadModule python_module modules/mod_python.soAddHandler mod_python .psp .psp_PythonHandler mod_python.pspPythonDebug On

第一行将 mod_python 加载到 Apache 中。mod_python.so 的实际路径可能会有所变化,但安装程序应在完成时给出正确的路径。(在 Linux 平台上,该路径很可能是 libexec/mod_python.so。)第二行将通知 Apache 应由第三行指定的 PythonHandler 处理的文件(以下部分将详细介绍 .psp_ 的用法)。最后一条指令会将 mod_python 切换到调试模式;在 PythonDebug 指令设为 On 时,它将在运行的应用程序中针对第一个未处理的异常转储跟踪。强烈建议在开发中设置该标志,但请确保在生产环境中将其关闭,以免向访问者暴露某些系统内部信息。

如果希望将 mod_python 页面用作默认索引页面,请在 httpd.conf 中找到以下行,并将其从

DirectoryIndex index.html index.html.var

更改为

DirectoryIndex index.html index.psp index.html.var

现在,重启 Apache。在 Windows 平台上,通常利用系统栏中的 Apache Monitor,或通过运行 net stop apache2 然后运行 net start apache2 来进行重启;在 Linux 平台上,重启就像 apachectl restart 一样简单。

使用 mod_python

PSP 是纯文本文件,其中包含带有 <%%> 标记的 Python 代码。Python 表达式包含在 <%=%> 标记中。指令支持将其他 PSP 页面包含在内;它们由 <%@%> 标记包装。最不常用的标记是 <%----%>,如您所猜,这两个标记只是不会出现在结果代码中的注释

让我们看一个简单的 Hello Python 示例。在 APACHE_HOME/htdocs 下,创建一个具有以下内容的文件 hello.psp:

<html><%import sys%>Hello!You have <%=len(sys.modules)%> Python modules at your command.</html>

现在,利用浏览器转至 http://127.0.0.1/hello.psp。您将会看到系统上安装的 Python 模块数量。当然,该信息对于我们而言用处不大。Mod_python 没有提供作用等同于 PHP 的 phpinfo() 的函数,该函数可以给出详细的解释器信息。在下一步中,我们将亲自为 PSP 编写一个函数。

在 APACHE_HOME/htdocs 下,创建一个具有以下内容的文件 pspinfo.psp:

<%%req.content_type = 'text/plain'import mod_pythonimport pprintimport sys%>PYTHON <%%=sys.version %>MOD_PYTHON <%%=mod_python.version %>PATH = <%%=pprint.pformat(sys.path)%>AVAILABLE MODULES<%%=pprint.pformat(sys.modules)%>

现在,打开 http://127.0.0.1/pspinfo.psp,您应当看到类似于下图所示的结果。

图 8

PSP 使用 Python 代码输出部分页面,这些页面使用以缩进为特征的块(类似 Python 本身)。最后一个缩进会一直存在,直至文档末尾或另一个 Python 块。请看以下示例 (blocks.psp)。

<%for i in range(5): j = 2**i # Loop block begins%><%="%d<sup>%d</sup>=%d"%(2, i, j)%><%# This will close the loop block%>Outside the loop block

在上例中,我同时使用了代码块 (<% %>) 和表达式 (<%= %>)。编写自己的脚本时,请留意二者之间的不同:表达式只能包含一个 Python 语句。如果您认为这种说法难以理解,请重新回顾一下前一步骤中的 Apache 配置。是否还记得 AddHandler mod_python .psp .psp_ 指令?现在,我们将利用调试 .psp_ 地址来看看幕后发生的事情。转至 http://127.0.0.1/blocks.psp,您将看到 PSP 生成的 Python 代码与源代码并排而列。

图 9

这对于我们深入了解呈现引擎非常有用。它还阐释了 mod_python 引擎背后的逻辑:在执行之前,PSP 页面会呈现为纯 Python 代码。

开始开发基本的 PSP 应用程序之前,最后需要了解的是会话和表单处理。请考虑以下这个基本的登录示例 (basic_login.psp)。页面上提供的口令应是反序 UID:

<%if 'uid' in form and 'passwd' in form and form['passwd']==''.join(reversed(form['uid'])): session['uid'] = form['uid']%>user <%=session['uid']%> logged in<%else:%><form action="basic_login.psp">UID<br<input type="text" name="uid"/><br/><br/>Password<br/><input type="password" name="passwd"/><br/><br/><input type="submit" value="Login"/></form><%#%>

PSP 的特色是具有两个重要的全局变量:formsession。这些是标准的 Python 字典。这将给予您最大的灵活度,但在分配变量时要小心,因为它们没有覆写保护。通过设置 session 字典变量的键值,即可设置会话变量:

session['variable'] = value

注意,Python 没有限制您使用字符串或整数作为字典键 — 任何可哈希的值都适用。例如,可在会话池中存储一个文件对象,以便在会话期间随时引用它。Mod_python 平等对待 GETPOST 请求,将它们存储在 form 字典中,易于查看用户是否已设置了该值。Python 字典有一些非常有用的内置方法,此时最便于使用的是:

  • D.keys() — 返回字典 D 键列表
  • D.has_key(k) — 如果字典 D 具有键 k,则返回 True,否则返回 False
  • D.get(k[, d]) — 如果 D 具有键 k,则返回值 D[k],否则返回 dd 默认为 None);这在表单处理中非常有用,例如 <%=form.get('is_sure', 'not sure')%>

cx_Oracle

利用 cx_Oracle Python 模块,可以轻松实现对 Oracle 数据库的访问。该模块由 Anthony Tuininga (Computronix) 根据 DB API 2.0 规范开发,这意味着,您使用同样的方法和属性组就可连接到 MySQL 或 PostgreSQL。

Cx_Oracle 具有 DB API 2.0 规范 (PEP 249) 的所有方法和属性,除了 nextset() 游标方法和 Binary() 构造函数。然而,请注意,cx_Oracle 向标准 API 引入了许多自己的扩展,从而极大地加强了与 Oracle 数据库的合作。这些扩展在 cx_Oracle 文档中都有详细描述,但一般而言,如果您过去使用的是 DB API 2.0,那么这些扩展对您来说应该毫不陌生。

安装 cx_Oracle

在 Windows 平台上:

  1. 下载 cx_Oracle-4.1.2-win32-10g-py24.exe,并双击下载的安装程序。
  2. 单击 Next 继续。
  3. 该安装程序将试图找到默认的 Python 2.4 解释器。要接受该选择,单击 Next
  4. 要开始安装过程,按 Next 按钮。
  5. 单击 Finish 完成安装。

在 Linux 平台上:

  1. 下载 cx_Oracle-4.1.2-10g-py24-1.i386.rpm,并将其置于系统的 /tmp 目录下。
  2. /tmp 目录下运行:
    $ rpm -ivh cx_Oracle-4.1.2-10g-py24-1.i386.rpm

使用 cx_Oracle

正如前面所述,cx_Oracle 基于 DB API 2.0 规范,因而用户使用起来非常简单。请参考以下示例,以熟悉连接至数据库并发出查询的基本步骤。在 APACHE_HOME/htdocs 下,创建文件 ora.psp 以查看 cx_Oracle 模块是否运行正常。(使用适用于配置的值替换用户名和口令。):

<%import cx_Oracledb = cx_Oracle.connect('username', 'password', '127.0.0.1/XE')c = db.cursor()c.execute('select * from dual')req.write(c.fetchall()[0][0])db.close()%>

当您打开 http://127.0.0.1/ora.psp 后,应当将浏览器中的 X 字符视为系统 DUAL 表中的唯一值。

后续步骤

刚才您为 PSP 和 Oracle 数据库 10g 设置了一个完整的工作环境,还了解了 Python Web 开发的基本知识。现在,您可以按照这个思路利用 PSP 编写复杂的应用程序,或切换至 mod_python 的 Publisher Handler,以提供更好的 MVC(模型-视图-控制器)策略。

目前有数个可用于 Python 的应用程序框架。尽管我建议您可以试一试,但这些框架要在企业级环境中使用还需进一步改进。Apache 以及 mod_python 本身对于处理大多数开发任务已经足够强大了。

原文: http://www.oracle.com/technology/global/cn/pub/articles/piotrowski-pythoncore.html

分类: 其他 标签:

【转】纯CSS实现圆角框(无图片背景方式)

2010年5月6日 没有评论

       纯CSS实现圆角框是一件大家都说烂了的事件,我也写过两篇总结文章,为什么还会有这篇文章呢,事情是这样的。在我们的以前的项目中,实现圆角框往 往是用背景图片来实现的,但是,当这些项目发布上线后,在维护过程中,有时需要添加一些新的需求,因为以前的项目中大量采用了圆角图片,并且这些图片全部 采用了CSSsprites方式合并的图,为了不增加更多的额外工作,并且也不想用JS来添加更多的http请求,所以需要一些简单的CSS方案来解决这个问题。而我 的个人爱好,也喜欢采用无图片的方式来处理这些效果。总觉得CSS能完成的工作,为什么不让它来实现呢?        武汉百度

实现原理:

纯CSS方式实现圆角框的原理在网络上已经有很多人详细解说了,下面这个示意图是我将其中的一个圆角进行放大后的效果。

图一

从上面效果图中我们可以看到其实这种圆角框是靠一个个容器堆砌而成的,每一个容器的宽度不同,这个宽度是由margin外边距来实现的, 如:margin:05px;就是左右两侧的外边距5像素,从上到下有5条线,其外边距分别为5px,3px,2px,1px,依次递减。因此根据这个原理我们可以实现简单的 html结构和样式。

1、Html结构层:

<div class="sharp color1">
<bclass="b1"></b><b class="b2"></b><bclass="b3"></b><b class="b4"></b>
<div class="content">文字内容</div>
</div>
<b class="b5"></b><b class="b6"></b><bclass="b7"></b><b class="b8"></b>  
</div>

b1~b4构成上面的左右两个圆角结构体,而b5~b8则构建了下面左右两个圆角结构体。而content则是内容主体,将这些全部放在一个大的容 器中,并给它的一个类名sharp,用来设置通用的样式。再给它叠加了一个color1类名,这个类名用来区别不同的颜色方案,因为可能会有不同颜色的圆 角框。

2、CSS样式:

.b1,.b2,.b3,.b4,.b5,.b6,.b7,.b8{height:1px;font-size:1px; overflow:hidden; display:block;}
.b1,.b8{margin:05px;}
.b2,.b7{margin:0 3px;border-right:2px solid; border-left:2pxsolid;}
.b3,.b6{margin:0 2px;border-right:1px solid; border-left:1pxsolid;}
.b4,.b5{margin:0 1px;border-right:1px solid; border-left:1pxsolid; height:2px;}

将每个b标签都设置为块状结构,并定义其高度为1像素,超出部分溢出隐藏。从上面样式中我们已经看到margin值的设置,是从大到小减少的。而 b1和b8的设置是一样,已经将它们合并在一起了,同样的原理,b2和b7、b3和b6、b4和b5都是一样的设置。这是因为上面两个圆和下面的两个圆是 一样,只是顺序是相对的,所以将它合并设置在一起。有利于减少CSS样式代码的字符大小。后面三句和第二句有点不同的地方是多设置了左右边框的样式,但是 在这儿并没有设置边框的颜色,这是为什么呢,因为这个边框颜色是我们需要适时变化,所以将它们分离出来,在下面的代码中单独定义。

接下我们设置内容区的样式:

.content {border-right:1px solid;border-left:1pxsolid;overflow:hidden;}

也是只设置左右边框线,但是不设置颜色值,它和上面八个b标签一起构成圆角框的外边框轮廓。

往往在一个页面中存在多个圆角框,而每个圆角框有可能其边框颜色各不相同,有没有可能针对不同的设计制作不同的换肤方案呢,答案是有的。在我的这个 应用中,可以换不同的皮肤颜色,并且设置颜色方案也并不是一件很难的事情。下面看看我是如何将它们应用到不同的颜色的。

在上面的样式设计中,我已经给颜色方案留下了可以扩展的空间。我将所有的涉及到边框色的类名全部集中在一起,用群选择符给它们设置一个边框的颜色就 可以了。如下所示:

.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,.color1.b6,
.color1 .b7,.color1 .content{}{border-color:#96C2F1;}
.color1.b1,.color1 .b8{background:#96C2F1;}

注意:需要将这两句的颜色值设置为一样的,第二句中虽说是设置的background背景色,但它同样是上下边框线的颜色,这一点一定要记住。因为 b1和b8并没有设置border,但它的高度值为1px,所以用它的背景色就达到了模拟上下边框的颜色了。
现在已经将一个圆角框描述出来了,但 是有一个问题要注意,就是内容区的背景色,因为这儿是存载文字主体的地方。所以还需要加入下面这句话,也是群集选择符来设置圆角内的所有背景色。

.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,
.color1.b6,.color1 .b7,.color1 .content{background:#EFF7FF;}

这儿除了b1和b8外,其它的标签都包含进来了,并且包括content容器,将它们的背景色全部设置一个颜色,这样除了线框外的所有地方都成为一 种颜色了。在这儿我也用到包含选择符,给它们都加了一个color1,这是颜色方案1的类名,依照这个原理可以设置不同的换肤方案。

好了,我们将上面的所有代码集中起来,就完成一个纯CSS圆角框的实例模型,在源码中,我设置了六套颜色方案,其它的颜色方案就看你的了。

下面是源码演示后的截图:

图二

为了演示效果,本模型的宽度值全部采用百分比实现的,你可以随意伸缩宽度,看看它能否适应弹性的变化。

本模型在以下浏览器中完美通过: 武汉百度推广

IE5.5、IE6、IE7、IE8、FF3、TT、Maxthon2.1.5、Opera9.6、Safari4.0、Chrome2.0。

分类: 前端技术 标签:

类与类关系的UML图与代码表现

2010年4月20日 没有评论

转过来的,乱的像三国,还是看原文吧

http://www.javaeye.com/topic/37302

类与类之间的关系对于理解面向对象具有很重要的作用,以前在面试的时候也经常被问到这个问题,在这里我就介绍一下。
类与类之间存在以下关系:
(1)泛化(Generalization)
(2)关联(Association)
(3)依赖(Dependency)
(4)聚合(Aggregation)

UML图与应用代码例子:
1.泛化(Generalization)
[泛化]
表示类与类之间的继承关系,接口与接口之间的继承关系,或类对接口的实现关系。一般化的关系是从子类指向父类的,与继承或实现的方法相反。
[具体表现]
父类 父类实例=new 子类()
[UML图](图1.1)



图1.1 Animal类与Tiger类,Dog类的泛化关系

[代码表现]

  1. class Animal{}   
  2. class Tiger extends Animal{}   
  3. public class Test   
  4. {   
  5.     public void test()   
  6.     {   
  7.         Animal a=new Tiger();   
  8.     }   
  9. }  


2.依赖(Dependency)
[依赖]
对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系。
[具体表现]
依赖关系表现在局部变量方法的参数,以及对静态方法的调用
[现实例子]
比如说你要去拧螺丝,你是不是要借助(也就是依赖)螺丝刀(Screwdriver)来帮助你完成拧螺丝(screw)的工作
[UML表现](图1.2)
(4)聚合(Aggregation)
[聚合]
当对象A被加入到对象B中,成为对象B的组成部分时,对象B和对象A之间为聚集关系。聚合是关联关系的一种,是较强的关联关系,强调的是整体部分之间的关系。
[具体表现]
与关联关系一样,聚合关系也是通过实例变量来实现这样关系的。关联关系和聚合关系来语法上是没办法区分的,从语义上才能更好的区分两者的区别。
[关联与聚合的区别]
(1)关联关系所涉及的两个对象是处在同一个层次上的。比如人和自行车就是一种关联关系,而不是聚合关系,因为人不是由自行车组成的。
聚合关系涉及的两个对象处于不平等的层次上,一个代表整体,一个代表部分。比如电脑和它的显示器、键盘、主板以及内存就是聚集关系,因为主板是电脑的组成部分。
(2)对于具有聚集关系(尤其是强聚集关系)的两个对象,整体对象会制约它的组成对象的生命周期。部分类的对象不能单独存在,它的生命周期依赖于整体类的对象的生命周期,当整体消失,部分也就随之消失。比如张三的电脑被偷了,那么电脑的所有组件也不存在了,除非张三事先把一些电脑的组件(比如硬盘和内存)拆了下来。
[UML图](图1.4)


图1.3 电脑和组件的聚合关系

[代码表现]



图1.2 Person类与Screwdriver类的依赖关系

[代码表现]

  1. public class Person{   
  2.     /** 拧螺丝 */  
  3.     public void screw(Screwdriver screwdriver){   
  4.         screwdriver.screw();   
  5.     }   
  6. }  


3.关联(Association)
[关联]
对于两个相对独立的对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联关系。
[具体表现]
关联关系是使用实例变量来实现
[现实例子]
比如客户和订单,每个订单对应特定的客户,每个客户对应一些特定的订单;再例如公司和员工,每个公司对应一些特定的员工,每个员工对应一特定的公司
[UML图] (图1.3)


图1.3 公司和员工的关联关系


[代码表现]

  1. public class Company{   
  2.     private Employee employee;   
  3.     public Employee getEmployee(){   
  4.         return employee;   
  5.     }   
  6.     public void setEmployee(Employee employee){   
  7.         this.employee=employee;   
  8.     }   
  9.     //公司运作   
  10.     public void run(){   
  11.         employee.startWorking();   
  12.     }   
  13. }  

  1. public class Computer{   
  2.     private CPU cpu;   
  3.     public CPU getCPU(){   
  4.         return cpu;   
  5.     }   
  6.     public void setCPU(CPU cpu){   
  7.         this.cpu=cpu;   
  8.     }   
  9.     //开启电脑   
  10.     public void start(){   
  11.         //cpu运作   
  12.         cpu.run();   
  13.     }   
  14. }  

[参考资料]
1.《Java与模式》(阎宏 编著) 第2章 统一建模语言UML简介

分类: 其他 标签:

纠结的UML类图元素关系

2010年4月20日 没有评论

主要是聚合和合成比较让人觉得纠结,不知道总结的对不对,先记下来再说

依赖 dependency        方法参数对象类型引用 function(className var)
关联 association          属性引用对象类型
聚合 aggregation           被引用对象所引用的对象不会因为引用对象的销毁而销毁
合成 composition         被引用对象所引用的对象因为引用对象的销毁百销毁
泛化 generalization      继承extends
实现 realization            实现implements

分类: 其他 标签: