FEEDS
RSS
Atom

整个过程十分的简单,部属方式也确实十分简单,它不像 wsgi 那么麻烦,整个体验十分的不错,这里记下来我的整个配置过程。

安装 UWSGI

默认系统并没有安装UWSGI,在使用前,必须得先安装它,我使用的是 Ubuntu 服务器,可以使用下面的方法安装它:

sudo -s
add-apt-repository ppa:nginx/stable
add-apt-repository ppa:uwsgi/release
apt-get update
apt-get install uwsgi-python python-virtualenv

你可以在运行上面的命令时, 会提示没有 "add-apt-repository" 的错误,这是因为这个工具并没有随Ubuntu一同安装,你需要自己安装它,安装方法是下面这行命令:

sudo apt-get install python-software-properties

从 Ubuntu 9.10 开始我们可以使用 add-apt-repository 命令(实质是个python脚本)在source.list里添加 ppa 源了(同时完成导入key)

创建Wiki站点的配置文件

我的维基架设在 http://wiki.costony.com 上,准备使用Nginx将其转发到 Unix Socket 上,我所使用的 Nginx 虚拟机的配置文件如下:

server {
    listen 80;
    access_log /home/wwwlogs/wiki.costony.com.access.log;
    error_log /home/wwwlogs/wiki.costony.com.error.log;

    server_name wiki.costony.com;
    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/wiki.costony.com.socket;
        uwsgi_param UWSGI_PYTHOME /home/websites/costony.com/wiki/moinenv/;
        uwsgi_param UWSGI_CHDIR /home/websites/costony.com/wiki/;
        uwsgi_param UWSGI_SCRIPT moin_wsgi;
        uwsgi_param UWSGI_SCHEME $scheme;
        uwsgi_param REMOTE_USER $remote_user;
    }

    location /moin_static194/ {
        alias /home/websites/costony.com/wiki/public/static/;
    }
}

从上面的配置中我们可以看到:

  • 我将Moin安装在它专用的 Virtuan Env中,同时,将其Static文件存放中一个特别的目录下,所以,这些都需要在安装 Moin的时候进行设定。

安装Python环境及 Moin

virtualenv /home/websites/costony.com/wiki/moinenv
cd /tmp
wget http://static.moinmo.in/files/moin-1.9.4.tar.gz
tar xvfz moin-1.9.4.tar.gz
source /home/websites/costony.com/wiki/moinenv/bin/activate
cd /tmp/moin-1.9.4
python setup.py install
deactivate
cp -r /tmp/moin-1.9.4/wiki /home/websites/costony.com/wiki
cd /home/websites/costony.com/wiki/wiki
mv wiki moin
cd moin
cp config/wikiconfig.py wikiconfig.py
cp server/moin.wsgi moin.wsgi
cp moin.wsgi moin_wsgi.py
cp /tmp/moin-1.9.4/MoinMoin/web/static/htdocs/* /home/websites/costony.com/wiki/public/static/
uwsgi-python -s /tmp/wiki.costony.com.socket --wsgi-file moin_wsgi.py -M -p 4 -d /home/wwwlogs/uwsgi.log

安装完成

这是一个简单的基于 ZODB3 的数据存储,定义了一个用户User类,一个应用 App 类,App类用来操作User数据,连接默认使用的 ZEO。你需要至少安装Python 2.3 及以上版本并且安装了 ZODB 3

#!/usr/bin/env python
# encoding: utf-8
"""
user.py
Created by pantao on 2012-04-17.
Copyright (c) 2012 aitine.com. All rights reserved.
"""
import sys, os
import transaction
from persistent import Persistent
from ZEO import ClientStorage
import ZODB
from ZODB.POSException import ConflictError
from BTrees import OOBTree

class User(Persistent):
    """Class for a user
    """
    def __init__(self, login, email, password):
        self.login = login.lower()
        self.email = email.lower()
        self.password = password

class App():
    """"""
    def __init__(self, conn):
        self.conn = conn
        self.root = self.conn.root()

    def get_users(self):
        if not self.root.has_key('users'):
            return None
        return self.root['users'].values()

    def add_user(self, user):
        if not self.root.has_key('users'):
            print('Create new ')
            self.root['users'] = OOBTree.OOBTree()
            transaction.commit()
        users = self.root['users']
        if not users.has_key(user.login):
            users[user.login] = user
            transaction.commit()
        else:
            return None
        return users[user.login]

def main():
    app = App(ZODB.DB(ClientStorage.ClientStorage('/tmp/zeosocket')).open())
    while 1:
        us = app.get_users()
        if us:
            for u in us:
                print('<User {} : {} >'.format(u.login, u.email))
        l,e,p = raw_input('Enter user info:').split(' ')
        u = User(l,e,p)
        app.add_user(u)

if __name__ == '__main__':
    main()

setuid、 setgid 和 sticky 权限

setuid、 setgid 和 sticky 权限这几个权限以前从来没有了解过,甚至都不知道有这么三种权限在这里,安装 FreeBSD 的时候,看到了,找了些资料,了解了一下下,这个东西不了解不知道,一了解,解了我很多迷题。

先回忆一下下Linux的权限,在Linux里面或者其它的类Unix系统中,权限是管理得很严格的,任何一个用户做任何事情都必须的相关的权限才行,别人的东西不让你看,你根本就会不知道有这么个东西,那么好了,现在就有了下面这几个问题:

  1. 普通用户修改自己的权限,要修改系统的密码数据库,那密码数据库是不是对所有用户开放?如果是的话,那密码数据还安全?如果不是的话,那为什么所有用户又都可以去修改?
  2. 系统的临时目录 /tmp 里面的所有东西,是规谁的?因为任何一个用户都对这个文件目录有写的权限,那也就是说任何用户都可以修改这个目录里面的内容了,那怎么办?我的临时文件别人也可以删除?

先想想我以前所了解的知识,这种问题还真没法儿解决,但是操作系统却已经解决得很好了,为什么?原因就是今天发现的这三种权限类型。这些权限对于一些 UNIX 操作而言很重要, 因为它们能提供一些一般情况下不会授予普通用户的功能。 为了便于理解, 我们首先介绍真实用户 ID (real user ID) 和生效用户 ID (effective user ID)。

真实用户 ID 是拥有或启动进程的用户 UID。 生效 UID 是进程以其身份运行的用户 ID。 举例来说, passwd(1) 工具通常是以发起修改密码的用户身份启动, 也就是说其进程的真实用户 ID 是那个用户的 ID; 但是, 由于需要修改密码数据库, 它会以 root 用户作为生效用户 ID 的身份运行。 这样, 普通的非特权用户就可以修改口令, 而不是看到 “Permission Denied” 错误了。

setuid 权限可以通过在普通权限前面加上一个数字四 (4) 来设置, 如下面的例子所示:

# chmod 4755 suidexample.sh

这样一来, suidexample.sh 的权限应该如下面这样:

-rwsr-xr-x   1 trhodes  trhodes    63 Aug 29 06:36 suidexample.sh

您会注意到, 在原先的属主执行权限的位置变成了 s。 这样, 需要提升特权的可执行文件, 例如 passwd 就可以正常运行了。

可以打开两个终端来观察这一情形。 在其中一个终端里面, 以普通用户身份启动 passwd 进程。 在它等待输入新口令时, 在另一个终端中查看进程表中关于 passwd 命令的信息。

在终端 A 中:

Changing local password for trhodes
Old Password:

在终端 B 中:

# ps aux | grep passwd
trhodes  5232  0.0  0.2  3420  1608   0  R+    2:10AM   0:00.00 grep passwd
root     5211  0.0  0.2  3620  1724   2  I+    2:09AM   0:00.01 passwd

正如前面所说的那样, passwd 是以普通用户的身份启动的, 但其生效 UID 是 root。

与此对应, setgid 权限的作用, 与 setuid 权限类似, 只是当应用程序配合这一设定运行时, 它会被授予拥有文件的那个组的权限。

如果需要在文件上配置 setgid 权限, 可以在权限数值前面增加数字二 (2) 来运行 chmod 命令, 如下面的例子所示:

# chmod 2755 sgidexample.sh

可以用与前面类似的方法来检视新设定的生效情况, 在组权限的地方的 s 表示这一配置已经生效:

-rwxr-sr-x   1 trhodes  trhodes    44 Aug 31 01:49 sgidexample.sh

注意: 在这些例子中, 尽管 shell 脚本也属于可执行文件的一种, 但它们不会以您配置的 EUID 或生效用户 ID 的身份运行。 这是因为 shell 脚本可能无法直接呼叫 setuid(2) 调用。

我们已经讨论了两个特殊权限位 (setuid 和 setgid 权限位), 它们让用户在使用程序时能够用到更高的权限, 有时这会削弱系统的安全性。 除了这两个之外, 还有第三个特殊权限位: sticky bit, 它能够增强安全性。

当在目录上设置了 sticky bit 之后, 其下的文件就只能由文件的所有者删除了。 这个权限设置能够防止用户删除类似 /tmp 这样的公共目录中不属于他们的文件。 要应用这种权限, 可以在权限设置前面加上数字一 (1)。 例如:

# chmod 1777 /tmp

现在, 可以用 ls 命令来查看效果:

# ls -al / | grep tmp
drwxrwxrwt  10 root  wheel         512 Aug 31 01:49 tmp

这里的结尾的 t 表示了 sticky bit 权限。

Markdown 语法介绍及使用说明

在教程正式开始之前,请先打开 Markdown 测试工具 ,这里面的所有示例都可以直接在该测试工具中测试。

Markdown 是这样两种东西,首先,他是一个格式化语法结构,其次他是一个使用Perl语言编写的用来实现Markdown至HTML转换的工具,它的设计目标就是让写作者尽可能使用容易阅读的语法书写,而不必被繁琐的HTML标签结构所纠缠,就像下面这样就可以创建一个一级标题的HTML结构:

# Markdown 介绍 #

Markdown 基本语法详解

使用 Markdown 一般情况下是没有可视化编辑界面的(Markdown与HTML的不同点在于它的设计初忠就是要写作者使用转Markdown代码(这里称之为代码吧,其实不是,它就是纯文本)),有一些网站在使用的时候,写作界面分为两个区域,预览区域和编辑区域,编辑区域就是写 Markdown,预览区会动态的将编辑区的修改即时的转换为HTML后展示出来以达到可视化编辑 的效果,但是我们这里所讲的,仅仅只是Markdown的语法。

段落、标题以及块引用

要使用 Markdown创建段落应该是最简单的了,只需要某一段文字顶头书写然后前后空行即可,这里不再做过多说明。

标题的创建也十分简单,这里有两种方法,最常用的就是在要作为标题的文字下一行(不空行)添加超一个的= 号或者 - 号,例如:

这是一个一级标题
==============

这是一个二级标题
---------------------------

将被转换成为:

<h1>这是一个一级标题</h1>

<h2>这是一个二级标题</h2>

另外一种创建标题的方法能创建出所有六级标题,它们分别是在要创建标题的那一行方案最前面顶行创建一个或者多个 # 号,并以相同数量的 # 结尾,比如:

### 这是三级标题 ###

##### 这是五级标题

将被转换成为:

<h3>这是三级标题</h3>

<h5>这是五级标题</h5>

你可以看到,后面结尾的 # 是可以省略的。

块级引用的创建是在需要作为块引用的所有文本行前面加上 > 符号,比如:

> 这是块引用的第一行,将会成为块引用中的一个段落
> 
> 这是块引用的第二段
> ## 这是块引用中的一个二级标题

转被转换成为下面这样的HTML代码:

<blockquote>
<p>这是块引用的第一行,将会成为块引用中的一个段落</p>

<p>这是块引用的第二段</p>

<h2>这是块引用中的一个二级标题</h2>
</blockquote>

加强与强调

Markdown 使用 星号(*) 与 下划线(_) 表示加强与强调,如下所示:

胡潇说:”我 *不想* 和鸟蛋睡一起!“
刘钊说:“我 _更不想_ 和潇老娘子睡一起!”

然后潘韬就说了:“你们两个都 **不要睡了** 吧!”
潘韬还说了:“ __都跟__ 哥睡!”

将被转换成为:

<p>胡潇说:”我 <em>不想</em> 和鸟蛋睡一起!“
刘钊说:“我 <em>更不想</em> 和潇老娘子睡一起!”</p>

<p>然后潘韬就说了:“你们两个都 <strong>不要睡了</strong> 吧!”
潘韬还说了:“ <strong>都跟</strong> 哥睡!”</p>

列表

无序列表可以使用星号,加号或者减号(*、+、-)创建,它们三者效果都是一样的,比如下的示例:

* 第一项
* 第二项
* 第三项

+ 第一项
+ 第二项
+ 第三项

还有

- 第一项
- 第二项
- 第三项

都会被转换成为:

<ul>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
</li>

有序列表则直接在每一项前面加上阿拉伯数字与小数点即可,如下:

1. 有序列表第一项
2. 有序列表第二项
3. 有序列表第三项

将被转换成为:

<ol>
<li>有序列表第一项</li>
<li>有序列表第二项</li>
<li>有序列表第三项</li>
</ol>

如果您在每一个列表项之间添加了一个空行,那么主会在每一个列表项中创建一个段落,比如:

* 这是一个列表项

  这是第一列表项中的第二个段落

* 这是列表的另一个项目

将被转换成为:

<ul>
<li><p>这是一个列表项</p>
<p>这是第一列表项中的第二个段落</p></li>
<li><p>这是列表的另一个项目</p></li>
</ul>

链接

Markdown使用两种方法创建链接,行内创建与引用创建,行内创建一般使用得比较多,它的创建语法是下面这样的:

这是一个示例[链接](http://aitine.com)。

转换成为:

<p>这是一个示例<a href="http://aitine.com">链接</a>。</p>

如果要为链接指定 title 属性,刚可以使用下面这样的:

这是一个示例[链接](http://aitine.com "这是一个标题")。

而以引用的方式创建链接一般用在学术论文上面比较多,或者另一种情况,如果某一个链接在文章中多处使用,那么使用引用 的方式创建链接将非常好,它可以让你对链接进行统一的管理,这有点类似于 LaTeX 对文档引用的管理,创建方法如下:

我最喜欢的几个网站是[Google][1] 、[艾天科技][2] 以及 [自己的博客][3],但是最喜欢的却是 [艾天项目管理平台][atoa],因为 [谷歌][1] 老是不能被访问到。

[1]:http://www.google.com "Google"
[2]:http://aitine.com "Aitine Technology"
[3]:http://note.costony.com "Notes of Cos Tony"
[atoa]:http://us.aitine.com "艾天项目管理平台"

转换后得到:

<p>我最喜欢的几个网站是<a href="http://www.google.com" title="Google">Google</a> 、<a href="http://aitine.com" title="Aitine Technology">艾天科技</a> 以及 <a href="http://note.costony.com" title="Notes of Cos Tony">自己的博客</a>,但是最喜欢的却是 <a href="http://us.aitine.com" title="艾天项目管理平台">艾天项目管理平台</a>,因为 <a href="http://www.google.com" title="Google">谷歌</a> 老是不能被访问到。</p>

从Markdown链接的引用创建方法中,你应该了解到一些基本的引用管理知识,要知道,专业的印刷行业里面、学术论文写作里面一般都不是使用 Word 或者什么可视化编辑工具来书写的,因为这些工具的引用管理功能都太弱了,而且使用起来十分的麻烦,一般都是使用 Tex 或者 LaTex ,有兴趣的可以去了解一下。

图片

图片的语法与链接的十分相似,行内创建时:

![Alt 文本](/path/to/img.jpg "图片 Title")

转换成为:

<p><img src="/path/to/img.jpg" alt="Alt 文本" title="图片 Title" /></p>

引用式创建也很相似:

![Alt 文本][id]

[id]:/path/to/img.jpg "标题"

转换结果是:

<p><img src="/path/to/img.jpg" alt="Alt 文本" title="标题" /></p>

可以看到图片与链接的引用方式创建时,引用格式是一样的,所以,一个引用可以同时被图片和链接所使用。

添加代码段

添加代码段应该是最简单的了,只需要把你想发布的任何代码不要顶头写就行,一般在前面留四个空格,比如:

我们的代码如下:

    <p>这是HTML代码</p>

转换后得到:

<p>我们的代码如下:</p>

<pre>&amp;lt;p&amp;gt;这是HTML代码&amp;lt;/p&amp;gt;&#10;    </pre>

所有以如特殊符号都会被自动转义。

Markdown 语法进阶

在 Markdown 中嵌入原生HTML代码

在 Markdown 代码中嵌入 HTML代码,如果你想直接在 Markdown 中嵌入HTML代码,那么你只需要将代码直接写在需要的地方即可:

这是一个段落。

<table>
    <tr>
        <td>这是用原生的HTML代码写的表格。</td>
    </tr>
</table>

这是另一个段落。

转换之后得到:

<p>这是一个段落。</p>

<table>
    <tr>
        <td>这是用原生的HTML代码写的表格。</td>
    </tr>
</table>

<p>这是另一个段落。</p>

你还需要注意的一点是,Markdown 是不处理HTML的块级元素中的内容的,比如你可以直接在 <p> 标签中使用 * 号:

<p>这是一个 *段落*</p>

在转换之后还是:

<p>这是一个 *段落*</p>

相反的,HTML的行内标签却可以在 Markdown 的语法的任何地方使用(除了代码段中):

这是一个文本段,<span>这个被span标签</span> 包裹了。

转换后得到:

<p>这是一个文本段,<span>这个被span标签</span> 包裹了。</p>

行内元素包括 spancitedel 等。

自动转义特殊字符

在HTML中,有两个字符是十分特殊的,他们是 < 和 & 符号,< 表示一个HTML标签的开始,&表示HTML特殊字符转义符的开始,在 Markdown 中这两个字符将会自动被转义,就如你刚才所看到的这一段话:

在HTML中,有两个字符是十分特殊的,他们是 < 和 & 符号,< 表示一个HTML标签的开始,&表示HTML特殊字符转义符的开始,在 Markdown 中这两个字符将会自动被转义,就如你刚才所看到的这一段话:

Markdown 转换之后得到的将是:

<p>在HTML中,有两个字符是十分特殊的,他们是 &lt; 和 &amp; 符号,&lt; 表示一个HTML标签的开始,&amp;表示HTML特殊字符转义符的开始,在 Markdown 中这两个字符将会自动被转义,就如你刚才所看到的这一段话:</p>

注意出现特殊符号的那几个位置。现在如果你想将一段文本指定到下面的这个URL中:

http://aitine.com/aitine?category=1&tag=3

Markdown 自动将您转换成为:

http://aitine.com/aitine?category=1&amp;tag=3

但是并不任何时候出现这些特殊自符的时候 Markdown 都会转义它们,比如前面说的,如果你写的就是完整的HTML代码,那么 Markdown 会不去管它,同样的,如果你写的是完整的HTML转义符,Markdown 也不会去管它,比如:

&copy;

Markdown 将不会去处理它,但是如果是:

AT&T

则会被转义成为:

AT&amp;T

块级元素

段落与分行

一个段落就是前面都有空行的一行或者多行文本(空行的意思是说你看上去像空行的东西,比如一行内没有任何内容或者一个或者多个空格或者制表符都属于空行),任何段落都不能以空格或者制表符开始。

在 Markdown 中,所谓的一行或者多行是指:没有空行分隔的任意行文本,这个和许多其它 文本至HTML转换工具不同,Markdown 使用的是 硬包裹,它不会像其它转换工具那样转换成为 <br /> 标签。

如果你是真的想在一个段落中插入一个 <br /> 标签,那么只需要在你想插入的地方输入两个或者两个以上的空格,然后回车,Markdown 就会在这里强制为你换行。

块级元素是可以嵌套的,比如一个 li 里面可能会嵌套的块引用,这时,块引用所使用的 > 符号应该再缩进了,比如下面这样的:

* 这是第一条引用项目

    > 这是第一条引用的内容

* 这是第二个项目

最终会被转义成为:

<ul>
<li><p>这是第一条引用项目</p>
<blockquote>
<p>这是第一条引用的内容</p>
</blockquote></li>
<li><p>这是第二个项目</p></li>
</ul>

在这里我们还需要注意另外一个问题,根据Markdown 对有序列表的定义,所有以数字后面跟着点开头的一行,都将成为一个有序列表,比如:

1234. 这其实并不是一个有序列表项目

也会被转换成为:

<ol>
<li>这其实并不是一个有序列表项目</li>
</ol>

如果有哪里必须这样的形式开头,你可以使用 \ 这个符号来明确的告诉 Markdown 这里是不需要转换的:

1234\. 这其实并不是一个有序列表项目

将被转换成为:

<p>1234. 这其实并不是一个有序列表项目</p>

代码块

对于程序员写作,经常需要在文章中嵌入代码段,在Markdown中,要嵌入代码段,只需要将每一行代码前都至少添加四个空格或者一个制表符(如果你想保证代码展示的方式和你想要的展示样式一样,那么最好每一行代码缩进的间距都是一行,我推荐都使用四个空格),Markdown 会将这样的文本都当作需要展示的文本内容(而不是可执行的代码),如果有需要转义的,比如 < 等都会被转义成为转义符,而整个代码段都会被 <pre> 以及 <code> 标签包裹。

这是一个普通的文本段落。

    但是这一行却会被当作是程序代码

上面的文字转换之后得到:

<p>这是一个普通的文本段落。</p>

<pre>&amp;lt;code&amp;gt;但是这一行却会被当作是程序代码&amp;lt;/code&amp;gt;&#10;    </pre>

如果要在行

分割线

你可以使用下面这种方法在内容中插入分割线 <br /> :   * * *

***

*************

- - -

---------------------

上面的任何一行都可以被转换成为:

<hr />

规则就是使用星号或者减号,排成一排,并且数量超过三个,任何两相相邻的符号之间的距离不能超一个空格

Plone主题默认提供了几个Portlet是无法在管理页面中去除的,但是我们的Diazo主题中可以加一个 portlets.xml 配置文件,然后使用下面的代码即可去除之:

<?xml version="1.0"?>
<portlets>
    <assignment remove="true" name="login" category="context" key="/" manager="plone.leftcolumn" type="portlets.Login" />
    <assignment remove="true" name="navigation" category="context" key="/" manager="plone.leftcolumn" type="portlets.Navigation" />
    <assignment remove="true" name="calendar" category="context" key="/" manager="plone.rightcolumn" type="portlets.Calendar" />
    <assignment remove="true" name="events" category="context" key="/" manager="plone.rightcolumn" type="portlets.Events" />
    <assignment remove="true" name="news" category="context" key="/" manager="plone.rightcolumn" type="portlets.News" />
    <assignment remove="true" name="recent-items" category="context" key="/" manager="plone.rightcolumn" type="portlets.recent" />
    <assignment remove="true" name="review" category="context" key="/" manager="plone.rightcolumn" type="portlets.review" />
</portlets>

确实是快要疯了,昨天为 Aitine 重新写了主题,基于 Diazo 的,但是在服务器上面怎么也无法安装,最让人头疼的是,在本地各种环境下都能使用,唯一不能使用的就是在服务器上面,这让人很恼火,昨天一个晚上也没有找哪里出错,因为是ZEO安装吧,Buildout时也不报错,使用启动脚本启动也不报错,但是就是启动不了。

今天找了一个以前在老服务器上可用的Diazo Plone Theme,发现也运行不了,这让我确定,并不是我的主题有问题,然后想到看看是不是服务器环境的问题,因为我就这两天把服务升级到了Ubuntu 64位服务器系统,接着我就把刚刚停用的32位系统启动,把主题在32位系统上面安装,没有什么问题,最终确定了:服务器环境的问题。

知道问题出在服务器上面,就好办事儿了,Diazo主题必须要有LXML支持,在其它环境都一致的情况下,只有可能是这个地方出问题,所以我就把 lxml 的 egg 删除之:

root@aitine:/usr/local/plone/buildout-cache/eggs# rm -rf lxml-2.2.8-py2.6-linux-x86_64.egg/

之后 还需要对 buildout.cfg 文件作如下修改:

[buildout]
parts =
     lxml # 保证 lxml 一直在第一位
     ...

之后重新 Buildout 出来,但是又出问题了,无法 buildout,报下面这个错误:

...
...
An error occured when trying to install lxml 2.2.8. Look above this message for any errors that were output by easy_install.
While:
  Installing instance.
  Getting distribution for 'lxml==2.2.8'.
Error: Couldn't install: lxml 2.2.8

这个在 这里 找到解决方法:

sudo apt-get install libxml2-dev libxslt-dev

这个安装完成之后,再重新 buildout 即可。

Plone 的时区设置

今天才发现的一个问题,使用Plone的安装包安装之后,默认情况下,站点使用的时区是美国的,所以,网站上面的时间一直都是不对的,以前也没有太在意这个玩意儿,但是今天朋友跟我说那个时间看上去很不爽,所以就研究了一下下Plone的时区设置,方法很简单,打开 buildout.cfg 文件,找到下面这段代码:

environment-vars =
    zope_i18n_compile_mo_files true
    PYTHON_EGG_CACHE ${buildout:directory}/var/.python-eggs
    #    TZ US/Eastern
    #    zope_i18n_allowed_languages en es de fr

并作下面这样的修改:

environment-vars =
    zope_i18n_compile_mo_files true
    PYTHON_EGG_CACHE ${buildout:directory}/var/.python-eggs
    TZ Etc/GMT+8
    #    zope_i18n_allowed_languages en es de fr

保存文件,然后重新执行 buildout 并重启 Plone 即可:

$ ./bin/buildout
$ ./bin/plonectl stop
$ ./bin/plonectl start

最小的 Plone 安装

我们除了使用完整的 Plone 安装 Plone 外,还可以使用更为高级的自定义安装方式安装,本文将介绍怎么从无到有使用 buildout 工具安装 Plone。

首先,我们需要创建一个文件夹,将来所有有关 Plone 的内容都将保存在这个目录中,即然是这样,那也就是说,其实你可以在一个系统中安装多个 Plone,要满足安装条件,我们还需要在系统中选安装 Python 2.6,我这里使用 virtualenv 工具创建一个虚拟机,在这个里面使用 Python 2.6

$ virtualenv —python=python2.6 /Users/pantao/VirtualEnv/plone
$ cd /Users/pantao/VirtualEnv/plone
$ source ./bin/activate

我们现在的工作目录就是 /Users/pantao/VirtualEnv/plone,我们将在这个目录下面来创建Plone Buildout。

接下来,下载 http:// svn.plone.org/svn/plone/buildouts/plone-coredev/branches/4.1/ bootstrap.py svn.plone.org/svn/plone/buildouts/plone-coredev/branches/4.1/ bootstrap.py 这个引文件,这个文件是用来创建 Buildout 工具的。

wget http:// svn.plone.org/svn/plone/buildouts/plone-coredev/branches/4.1/ bootstrap.py

第三步就是在当前目录下创建一个名为 buildout.cfg 的文件,将下面的内容添加到该文件 中:

[buildout]
extends =
    http://dist.plone.org/release/4.1/versions.cfg
    parts = instance
[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
eggs = Plone

现在我们可以初始化 buildout 了,在当前目录下面,运行下面这一行命令:

$ python bootstrap.py —distribute

这里,我直接使用 python 来运行它 bootstrap.py 是因为我们现处于 Virtual env 中,而这个 Vittual env 就是 Python 2.6 的,但是如果你是进行全局安装,那么有可能直接执行 python 命令运行的并不是 Python 2.6,这个需要你就需要在这里给出完整的 Python 2.6 的目录,比如我的本本上面, Python 2.6 的完整路径是下面这样的:

/System/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6

接着,我们执行下面命令来将 Plone buildout 出来,这个过程会从网络上下载很多文件,包括 Zope、Plone 本身以及其它一些需求包,根据网速,可能会需要不同的时间, Buildout 过程完成之后,就可以使用下面命令以 Debug 模式启动 Plone 了:

$ ./bin/instance fg

当脚本提示你已经 Ready for request 的时候,你就可以通过:“http://localhost:8080/”:http://localhost:8080/ 来访问你刚才创建的 Plone 站点。

创建Plone主题

Plone 主题可以通过 ZMI 直接在后台进行修改,但是这也只能满足一部分需求,如果我们需要更多可定制的操作,那么就需要完全的创建新的主题,在 Plone 中要创建一个主题,很简单。

使用 paster 创建 Plone 主题

Plone 安装完成之后,在 {instance_path}/bin 目录中,就有 paster,通过它,我们可以创建许多东西,比如创建新的 content type,在这里,我们就使用它来创建新的 Plone 主题。

首先,进入 {instance_path}/src/ 目录:

cd /path/to/instance/src

之后运行下列命令:

../bin/paster create -t plone3_theme aitinetheme.aitine

然后脚本会询问你一些问题,你只需要按着你的实际情况以脚本提供的格式回复即可。脚本运行完成之后,就会在 ./src 目录中生成 aitinetheme.titine 目录,这就是新的 plone 主题目录,之后的所有操作都将在该目录中进行。

使用 sc.paster.theme 创建 plone 主题

本文重点将介绍使用 sc.paster.theme 这个工具来创建 plone 主题,虽然和 paster 有点像,但是我个人还是更喜欢这个工具。

安装 sc.paster.theme

该工具并没有默认提供,我们需要先安装它,使用 easy_install 命令即可,在这里,我们有一点需要记住,如果你的 Zope 服务器使用的是自带的 Python ,那么,你不能直接执行 easy_install ,因为这样会将其安装到全局的 Python 环境中,我们需要指出 Zope 服务器所使用的 Python 路径,比如:

/Applications/Plone/Python-2.6/bin/easy_install -U sc.paster.theme

安装需要 gcc 等工具,你需要先安装,如果你在 Mac OS X 下安装,那么需要安装 XCode 命令行工具集才行,如果你是在 Windows 下面安装,对不起,哥真不知道应该怎么整。

{instance_path}/bin 目录中创建 sc.paster.theme 脚本的快捷方式

sc.paster.theme 安装完成之后,进入 {instance_path}/bin 目录,创建 sc.paster.theme 的链接文件,我这里使用的是硬链接,当然一定要记住,你需要为其重新命名,因为 Plone 本身已经有了一个 paster 脚本了。

ln /Applications/Plone/Python-2.6/bin/paster ./sc_paster

使用 sc.paster.theme 创建 Plone 主题

与 paster 一样,先进入 src 目录,然后执行下面这行命令:

../bin/sc_paster create -t portal_theme aitine.theme.aitine

该命令同样会询问你一些问题,你一样需要一个一个回答,如果按我创建我的 aitine.theme.aitine 这个主题来讲的话,整个命令的运行流程如下:

PanTao-Macbook-Pro:src pantao$ ../bin/sc_paster create -t portal_theme aitine.theme.aitine
Selected and implied templates:
  sc.paster.theme#portal_theme  Tema visual para projetos Plone 3
Variables:
  egg:      aitine.theme.aitine
  package:  aitinethemeaitine
  project:  aitine.theme.aitine
Expert Mode? (What question mode would you like? (easy/expert/all)?) ['easy']: all
Namespace Package Name (Namespace principal) ['aitine']: 
Namespace 2 Package Name (Usualmente o nome do cliente) ['theme']: 
Package Name (Nome do projeto) ['aitine']: 
Description (One-line description of the project) ['']: A plone theme designed by aitine.com, for Aitine.
Creating template portal_theme
Creating directory ./aitine.theme.aitine
  Recursing into +namespace_package+
    Creating ./aitine.theme.aitine/aitine/
    Recursing into +namespace_package2+
    ......
    Copying LICENSE.GPL to ./aitine.theme.aitine/docs/LICENSE.GPL
    Copying LICENSE.txt_tmpl to ./aitine.theme.aitine/docs/LICENSE.txt
  Copying setup.cfg to ./aitine.theme.aitine/setup.cfg
  Copying setup.py_tmpl to ./aitine.theme.aitine/setup.py
Running /Applications/Plone/Python-2.6/bin/python setup.py egg_info

中间很长一段信息已经被我省略了,之后,我们在 src 目录中,就会得到一个名为:@aitine.theme.aitine@ 的文件夹,它就是我们的主题。之后我们还需要将其添加到 buildout.cfg 文件中,添加方式如下:

eggs =
    ......
    aitine.theme.aitine
zcml =
    ......
    aitine.theme.aitine
develop =
    ......
    src/aitine.theme.aitine

添加完成之后,我们需要更新我们的 instance,然后再以 fg 模工运行 Plone:

PanTao-Macbook-Pro:zinstance pantao$ ./bin/buildout 
Develop: '/Applications/Plone/zinstance/src/aitine.theme.aitine'
Uninstalling zopeskel.
......
PanTao-Macbook-Pro:zinstance pantao$ ./bin/plonectl fg
instance: 2012-03-19 20:47:44 INFO ZServer HTTP server started at Mon Mar 19 20:47:44 2012
	Hostname: 0.0.0.0
	Port: 8080
2012-03-19 20:47:45 WARNING SecurityInfo Conflicting security declarations for "setText"
2012-03-19 20:47:45 WARNING SecurityInfo Class "ATTopic" had conflicting security declarations
2012-03-19 20:48:01 INFO Zope Ready to handle requests

当你看到 Zope Ready to handle requests 信息时,你的 Plone 已经以 fg 模式运行成功了,现在你需要进入你的开发站点,启用这个主题即可,以 fg 模式运行时,你对主题的修改能即时的展示在前端。

Plone站点安装好了之后,我们总不能永远都使用Plone默认提供的功能和样式,总得根据自己的需要安装一些新的插件,修改修改主题或者安装新的主题,本文记录Plone新插件的安装方法与主题的简单自定义。

安装新的插件

最简单地安装Plone插件方法就是将想要安装的插件名称添加到 buildout.cfg 文件中,如下代码所示:

############################################
# Eggs
# ----
# Add an indented line to the eggs section for any Python
# eggs or packages you wish to include.
#
eggs =
    Plone
    Pillow
    lxml
    Products.PloneFormGen
    webcouturier.dropdownmenu
    collective.easyslider

在上面的代码中,我们除了Plone系统默认安装的插件外,还安装了三个新的插件:@Products.PloneFormGen@、@webcouturier.dropdownmenu@、@collective.easyslider@,这三个插件分别让我的Plone站点可以添加自定义表单,有下拉菜单,还可以很方便在页面中添加Slides。

将新的插件的名称添加到 buildout.cfg 文件中的 eggs 段之后,我们需要更新Plone,重新 buildout 它。

首先我们需要进入 buildout.cfg 文件所在的目录(这是必须在,在其它目录中,是无法更新 Plone 的,会提示找不到 buildout.cfg 文件,进入该目录之后,运行下面的命令:

./bin/buildout
PanTao-Macbook-Pro:zinstance pantao$ ./bin/buildout 
Uninstalling instance.
Installing instance.
Updating zopepy.
Updating zopeskel.
Updating backup.
Updating chown.
chown: Running echo Dummy references to force this to execute after referenced parts
echo /Applications/Plone/zinstance/var/backups 
chmod 600 .installed.cfg
find /Applications/Plone/zinstance/var -type d -exec chmod 700 {} \;
chmod 744 /Applications/Plone/zinstance/bin/*
Dummy references to force this to execute after referenced parts
/Applications/Plone/zinstance/var/backups
Updating repozo.
Updating unifiedinstaller.
*************** PICKED VERSIONS ****************
[versions]
Products.PloneFormGen = 1.7.0
Products.PythonField = 1.1.3
Products.TALESField = 1.1.3
Products.TemplateFields = 1.2.5
collective.easyslider = 0.7.4
collective.js.jqueryui = 1.8.13.1
webcouturier.dropdownmenu = 2.3
*************** /PICKED VERSIONS ***************

之后我们需要停止当前正在运行的Plone Instance,然后再重新开启它:

PanTao-Macbook-Pro:zinstance pantao$ ./bin/plonectl stop
instance: . 
daemon process stopped
PanTao-Macbook-Pro:zinstance pantao$ ./bin/plonectl start
instance: . . 
daemon process started, pid=1417

重新启动之后,我们还需要进入站点的设置页面,找到附加组件,就可以看到我们刚刚安装的新组件了,这个时候我们就可以启动或者关闭组件。

自定义Plone站点样式

自定义Plone站点样式,我们可以开发新的主题,但是最简单的,莫过于修改Plone现有的主题。

修改 Plone 站点的 Logo

要修改 Plone 站点默认的 Plone Logo,我们可以以管理员身份登陆站点,然后进入 ZMI( 进入站点设置页面,找到 Zope 管理界面,即进入了 ZMI),在该页面中,进入 portal_skins -> portal_images,之后我们可以看到 logo.png文件,点击这个文件,之后在进入的页面,点击 customize,即可自定义该 Logo,上传我们自己的 logo,之后保存,再返回网站前端就可以看到新的 Logo 已经修改好了。

修改 Plone 站点的 CSS 样式表

Plone 并不建议修改它本身自带的样式表(几乎所有现代的CMS都不建议这么做),而是使用新的样式去覆盖它本身的样式,现在我们要修改 Plone 的样式表的话,首先需要开启 Plone 站点的开发者模式(Debug Mode),重新打开 buildout.cfg 文件,找到下面这段代码:
############################################
# Debug Mode
# ----------
# Change debug-mode to "on" to run in development mode.
# This will dramatically slow Plone.
# 
debug-mode = off

将 debug-mode 打开,即修改成为下面这一行:

debug-mode = on

之后和安装新的组件一样,需要更新 Plone Instance,更新完了之后,进入ZMI,找到 portal_skins -> portal_styles,之后你可以看到 ploneCustom.css文件,我们只需要 将新的样式加入到这个文件之后,再保存即可。

- Older Posts »