个人工具

首页/Python/三十分钟学会Zope3

来自Ubuntu中文

跳转至: 导航, 搜索

Zope3 In 30 Minutes(三十分钟学会Zope3)

Author: Baiju M <baiju.m.mail AT gmail.com>
Version: 0.1.4
Copyright: (C) 2005 Baiju M, Placed under GNU GPL version 2, or (at your option) any later version
翻译:firehare
校正:leal
组织:ubuntu.org.cn


Contents 目录

Important Note: I assume you are using Debian 3.1 (Sarge) or similar systems.

特别注意:我假设你正在使用Debian3.1(Sarge)或相似系统

Anchor(why30)

Why 30?(为什么是30分钟)

Sorry! Zope3 cannot be introduced in 10 minutes.

很抱歉!Zope3是不可能在10分钟内介绍清楚的

Anchor(whyi)

And why should I ...?(为什么我要学...?)

If you are looking for a Pythonic framework for web application development, just continue reading. And I am not going to make a new definition for What is Pythonic? Smile . Here I will try to answer your "why?" questions.

如果你想为基于Web的应用开发作一个Pythonic的框架,那么请继续。我并不打算对什么是Pythonic作任何新的解释Smile,主要试图回答“为什么”的问题。

Anchor(key)

Keywords(关键词)

Python, Zope, Interface, Component, ZCML, ZMI, Adapter, View, Event, Service, Utility, Principal.

Anchor(start)

So let's start...(那么让我们开始...)

Zope3 is the third generation of Zope, a framework for web applications. You can download Zope 3.1 from http://www.zope.org/Products/Zope3 . To install untar Zope3 source package, then as root:

Zope3是第三代的Zope,一个Web应用框架。你可以从http://www.zope.org/Products/zope3下载Zope3.1,解压Zope3源包,并以根用户权限运行:

# cd Zope-3.1.0
# ./configure;make;make install
译者的话:
如果是在Ubuntu下,请按下面命令运行:
$tar -zxvf Zope-3.1.0.tgz -C /tmp
(如果是Breezy下,请安装Python2.3 Python2.3-dev等相关包,因为Zope3是基于Python2.4.1和Python2.3.5开发的,而Breezy默认是Python2.4.2,所以必须安装Python2.3的包文件了)
$./configure --prefix /opt/zope
$make
$make check
$make install

After installation you have to make an instance (don't worry! just do it). To do so:

安装完成后,你必须建立一个Zope Instance(别担心!只需照作就行)。命令如下:

$ cd /usr/local/Zope-3.1.0/bin
$ ./mkzopeinstance --dir=$HOME/myzope --user=admin:secret123

To start Zope3 server, go to your instance directory, then:

然后是启动你的Zope3服务,到你的Instance目录下,然后运行:

$ cd ~/myzope
$ ./bin/runzope

If you get a port error, check check 8080 and 8021 is already used by other programs; for the time being, just stop it. Start your browser , the open http://localhost:8080 . What you see is the Zope Management Interface (ZMI). ZMI is your Python prompt, hmm... no! Zope prompt, got it?. You can login and look around to see what's happening. If you played enough with ZMI, stop it from terminal (Control + C).

如果你得到一个端口错误,请检查8080和8021端口是否被其他程序占用;暂时停止运行该程序。打开你的浏览器,然后输入http://localhost:8080。你将看到Zope Management Interface(ZMI)。ZMI是你的Python提示符,嗯...不!应该是Zope的提示符,看到了吗?你可以登录进去并且到处点击看看。如果你在ZMI玩够了的话,在终端用Ctrl+C中断它。

Anchor(bookmarker)

BookMarker : Your first Zope3 app(BookMarker:你的第一个Zope3应用)

Yes! we are going to create a Zope3 application, an online book marker. Our app will display links to websites and a description for each link.

是的!我们打算开始创建一个Zope3应用,一个在线书签。我们的应用将显示到网站的链接和每条链接的描述。

So, what you have to think about when you start a Zope3 project. Oh! sorry! I can't put it in one sentence, you better learn and practice Extreme Programming http://en.wikipedia.org/wiki/Extreme_programming . Anyway, after your initial design, you will write interfaces. Let us hope Python 3.0 will make it much easier. Then you will write unit tests, now your ideas become very concrete!. At last write your real code. You will be satisfied when you implement interfaces one by one and unit tests succeeds!. I have given the source code of BookMarker here: boom.tar.bz2

那么,在开始一个Zope3项目前,你得做何准备呢?哦!很抱歉!我没法一言以蔽之,你最好先学习并实践XP(极限编程,一种轻量级的软件开发过程) http://en.wikipedia.org/wiki/Extreme_programming 。总之,在你初步设计之后,就将编写接口。让我们期待Python 3.0 会让它变得容易些吧!然后开始编写单元测试,至此你的想法已非常具体!最后编写正式代码。当你一个接一个的实现接口并通过单元测试,你会拥有(前所未有的)满足感! 我已经在这里给出了BookMarker应用的源代码:boom.tar.bz2

Our code will be placed at $HOME/myzope/lib/python/boom

我们的代码将放在$HOME/myzope/lib/python/boom目录中

First create a file interfaces.py where we will keep our interfaces. Later we will implement these interfaces one by one, with strong support of unit testing.

首先创建一个interfaces.py的文件,我们将在该文件内保存所有接口。后面我们将在单元测试的强力支持下,一个接一个的实现这些接口。

Anchor(interface)

Interfaces(接口)

Here is our interfaces.py:

下面就是我们的interfaces.py:

#!python
from zope.interface import Interface
from zope.schema import Text, TextLine, Field

from zope.app.container.constraints import ContainerTypesConstraint
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.container.interfaces import IContained, IContainer

class IMark(Interface):
"""This is the book mark object."""

url = TextLine(
title=u"URL/Link",
description=u"URL of the website",
default=u"http://www.zope.org",
required=True)

description = Text(
title=u"Description",
description=u"Description of the website",
default=u"",
required=False)

class IBookMarker(IContainer):
"""This is the container for all book marks."""

name = TextLine(
title=u"Name of BookMarker",
description=u"A name for BookMarker",
default=u"",
required=True)

def <u>setitem</u>(name, obj):
pass

<u>setitem</u>.precondition = ItemTypePrecondition(IMark)


class IMarkContained(IContained):
"""A book mark can only contain in a BookMarker"""

<u>parent</u> = Field(
constraint = ContainerTypesConstraint(IBookMarker))

Our first interface IMark has two attributes, one is the URL of the site and the other one is the description. Please note, IMark is not a class even though we used Python's class definition. We inherited from Interface to make it an interface. Second one is a container interface, which is an extended IContainer interface. By using this container interface we can persist our data (instances of IMark implementations). We will put all objects of IMark in a container object of IBookMarker. We will implement IMark along with IMarkContained as a constraint interface. So that IMark object will be only contained in an IBookMarker object.

我们的第一个接口IMark有两个属性,一个是站点的URL,另一个是它的描述。请注意,IMark不是一个类,尽管我们使用了Python的类定义。IMark继承自Interface,因此是个接口。第二个是一个容器接口,它是一个扩展的IContainer接口。我们可以使用这个容器接口来保存我们的数据(IMark实现的实例)。我们将IMark的所有对象放到IBookMarker的一个容器对象里。我们连同IMarkContained(作为一个约束接口)一起来实现IMark。所以IMark对象只能包含在IBookMarker对象中。

Anchor(unittest)

Unit Testing(单元测试)

Now create tests.py and put the following code there:

现在创建tests.py文件,输入下列语句:

#!python
import unittest
from zope.testing.doctestunit import DocTestSuite

from zope.app.container.tests.test_icontainer import TestSampleContainer

from boom.bookmarker import BookMarker, Mark


class BookMarkerContainerTest(TestSampleContainer):

def makeBookMarkerObject(self):
return BookMarker()

def test_suite():
return unittest.TestSuite((
DocTestSuite('boom.bookmarker'),
unittest.makeSuite(BookMarkerContainerTest),
))

if <u>name</u> == '<u>main</u>':
unittest.main(defaultTest='test_suite')

Actually, we are not written any unit tests here, but this will make our doc tests working automatically.

实际上我们在这里并没有编写任何的单元测试,不过它会自动对我们的文档进行测试

To run the unit test:

然后运行单元测试

$ cd $HOME/myzope/lib
$ ../bin/test -vpu --dir boom

Anchor(realcode)

Real coding!(正式编码)

Now let's move on to the implementation (bookmarker.py):

现在让我们继续去实现(bookmarker.py)

#!python
<u>docformat</u> = 'restructuredtext'

from zope.interface import implements
from zope.app.container.btree import BTreeContainer
from zope.app.container.contained import Contained

from boom.interfaces import IMark, IMarkContained, IBookMarker

class Mark(Contained):
"""Implementation of IMark

Make sure that the `Mark` implements the `IMark` interface::

>>> from zope.interface.verify import verifyClass
>>> verifyClass(IMark, Mark)
True

Make sure that the `Mark` implements the `IMarkContained` interface:

>>> from zope.interface.verify import verifyClass
>>> verifyClass(IMarkContained, Mark)
True

An example of checking the url of Mark::

>>> mk = Mark()
>>> mk.url
u'http://www.zope.org'
>>> mk.url = u'http://www.python.org'
>>> mk.url
u'http://www.python.org'

An example of checking the description of Mark::

>>> mk = Mark()
>>> mk.description
u''
>>> mk.description = u'Zope Project Web Site'
>>> mk.description
u'Zope Project Web Site'
"""

implements(IMark, IMarkContained)

url = u"http://www.zope.org"
description = u""


class BookMarker(BTreeContainer):
"""Implementation of IBookMarker using B-Tree Container

Make sure that the `BookMarker` implements the `IBookMarker` interface::

>>> from zope.interface.verify import verifyClass
>>> verifyClass(IBookMarker, BookMarker)
True

An example of changing the name of BookMarker::

>>> bm = BookMarker()
>>> bm.name
u''
>>> bm.name = u'MyBookMarker'
>>> bm.name
u'MyBookMarker'
"""

implements(IBookMarker)

name = u""

We have written doctests along with the implementations. Doctests are accompanied with examples, so it is called example driven unit testing.

我们已经在实现的同时也编写了Doctests,该Doctests是同例子一起的,所以这种实现方式我们称之为事例驱动单元测试

Anchor(config)

Configuration(配置)

Now configuration (save in configure.zcml):

现在编写配置(保存在configure.zcml文件中):

<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">

<interface
interface=".interfaces.IBookMarker"
type="zope.app.content.interfaces.IContentType"
/>

<content class=".bookmarker.BookMarker">
<implements
interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
/>
<implements
interface="zope.app.container.interfaces.IContentContainer"
/>
<factory
id="boom.bookmarker.BookMarker"
description="Book Marker"
/>
<require
permission="zope.ManageContent"
interface=".interfaces.IBookMarker"
/>
<require
permission="zope.ManageContent"
set_schema=".interfaces.IBookMarker"
/>
</content>

<interface
interface=".interfaces.IMark"
type="zope.app.content.interfaces.IContentType"
/>

<content class=".bookmarker.Mark">
<implements
interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
/>
<factory
id="boom.bookmarker.Mark"
description="A book mark."
/>
<require
permission="zope.ManageContent"
interface=".interfaces.IMark"/>
<require
permission="zope.ManageContent"
set_schema=".interfaces.IMark"
/>
</content>

<browser:addform
label="Add Book Marker"
name="AddBookMarker.html"
schema="boom.interfaces.IBookMarker"
content_factory="boom.bookmarker.BookMarker"
fields="name"
permission="zope.ManageContent"
/>

<browser:addMenuItem
class=".bookmarker.BookMarker"
title="Book Marker"
permission="zope.ManageContent"
view="AddBookMarker.html"
/>

<browser:editform
schema="boom.interfaces.IBookMarker"
for="boom.interfaces.IBookMarker"
label="Change Book Marker"
name="edit.html"
permission="zope.ManageContent"
menu="zmi_views" title="Edit"
/>

<browser:containerViews
for="boom.interfaces.IBookMarker"
index="zope.View"
contents="zope.View"
add="zope.ManageContent"
/>

<browser:addform
label="Add Mark"
name="AddMark.html"
schema="boom.interfaces.IMark"
content_factory="boom.bookmarker.Mark"
fields="url description"
permission="zope.ManageContent"
/>

<browser:addMenuItem
class="boom.bookmarker.Mark"
title="Mark"
description="URL of Website"
permission="zope.ManageContent"
view="AddMark.html"
/>

<browser:editform
schema="boom.interfaces.IMark"
for="boom.interfaces.IMark"
label="Change Mark"
fields="url description"
name="edit.html"
permission="zope.ManageContent"
menu="zmi_views" title="Edit"
/>

<browser:page
name="marks.html"
for="boom.interfaces.IBookMarker"
class=".browser.BookMarks"
template="marks.pt"
permission="zope.Public"
menu="zmi_views"
title="Marks"
/>

</configure>

Is it self explanatory? "no...!" then ok! we will discuss Zope Configuration Markup Language (ZCML) briefly later. Actually, if you are familiar with ZCML this configuartion will be more than self explanatory. It will give you an overall idea about the entire application. Now you might think, it is not Pythonic Sad Hey! think twice!.

它能不言自明(即能够自我解释,XML之类的标记语言都有这个特点)吗?“不...!”好吧,我们将稍后简单的谈谈Zope Configuration Markup Language(ZCML,Zope配置标记语言)。实际上,如果你对ZCML熟悉的话,你会发现这个配置不止是不言自明,它将带给你的是对整个应用的总体思路。现在你可能在想,这并不Pythonic嘛 Sad ,嗨!再想想!

Anchor(runit)

Just run it

As the last step to work our application, put the following line in:$HOME/myzope/etc/package-icludes/boom-configure.zcml:

最后一步就是要让我们的应用运行起来,在文件$HOME/myzope/etc/package-icludes/boom-configure.zcml中插入下列行:

<include package="boom"/>

Now you registered your package.

现在你已经注册了你的包。

Run zope again, then open your browser, add a BookMarker and few book marks.

重新启动Zope,然后打开你的浏览器,添加一个BookMarker和一些书签。

Now you want to arrange your your book marks in a better way, don't you?. For the time being, just relax, then we will create a view for book marks.

现在,你不想让你的书签排列得更好点吗?先暂时休息一下,之后我们将为书签创建一个视图。

Anchor(view)

Views(视图)

Now create a file named browser.py with following code:

现在新建一个名为browser.py的文件,并输入下列代码:

#!python

from boom.interfaces import IMark

class BookMarks:

def <u>init</u>(self, context, request, base_url=''):
self.context = context
self.request = request
self.base_url = base_url

def listMarks(self):
marks = []
for name, child in self.context.items():
if IMark.providedBy(child):
info = {}
info['url'] = child.url
info['description'] = child.description
marks.append(info)
return marks

Then one template (marks.pt):

然后创建一个模板(marks.pt)

<nowiki>
<html metal:use-macro="views/standard_macros/view">
<body>
<div metal:fill-slot="body">

<div class="row">
<div class="label">Book Marks:</div>
<br/><br/>
<li tal:repeat="item view/listMarks">

<a href="" tal:attributes="href item/url">
<span tal:content="item/url">Link</span>
</a>
<pre tal:content="item/description">Description


</li> </div>

</div> </body> </html> </nowiki></pre>

Now by clicking on "Marks" tab you can see all book marks.

现在点击一下“Marks”标签,你就可以看到所有的书签了。

Ok! this is not the end, just the beginning of your study.

好的!这样可不能算是结束,这仅仅是你学习的开始。

Anchor(functest)

Functional testing(功能测试)

Let's finish our example writing a functional test for view (ftests.py):

让我们为视图写一个功能测试来结束我们的例子(ftests.py)

#!python

import unittest
from zope.app.testing.functional import BrowserTestCase

class BookMarksTest(BrowserTestCase):

def testMarksListing(self):
pass


def test_suite():
return unittest.TestSuite((
unittest.makeSuite(BookMarksTest),
))

if <u>name</u> == '<u>main</u>':
unittest.main(defaultTest='test_suite')

To run the functional test:

$ cd $HOME/myzope/lib
$ ../bin/test -vpf --dir boom

Anchor(nowwhat)

Now what?(现在学什么?)

Now you can start learning Zope3 in detail, using Zope3 book. Also join zope3-users mailing list.

现在你可以通过Zope3 Book开始详细学习Zope3了。也可以加入到zope3-user邮件列表里。

There is a good Zope3 quick start guide by Benji York: http://www.benjiyork.com/quick_start/

这里有Benji York写的一个不错的Zope3快速入门指南: http://www.benjiyork.com/quick_start/

A good introductory book is also available in print, visit: http://worldcookery.com/

还有一本已出版的介绍性图书,很不错,请访问: http://worldcookery.com/

Just one more thing: I want to improve this document, so don't hesitate to write your feedback to: baiju.m.mail AT gmail.com

还有一点:我想不断完善这份文档,因此有何意见/建议千万别犹豫,请发送到: [email protected]

Anchor(whattime)

Hey! What's time now?(嗨!现在什么时候了?)

Oh! it's only 10 minutes since we started reading this article. We got 20 more minutes to explain what's happened here. So let's look back again.

哦!从我们开始看这篇文章到现在才花了10分钟。我们还有20分钟的时间来解释这里发生了什么。那么让我们回过去看看

Anchor(instconf)

Installation and Configuration(安装和配置)

You can download Zope 3.1.0 or later for your major works. Install Zope3 as root, though it is not necessary. When you experiment with Zope3, make instance as a normal user. For production systems, you get the additional advantage of OS level security. Since we manually installed Zope3 (as root), the default installation path will be /usr/local/Zope-3.1.x . When making zope instance, you have to specify zope manager's user name and password. You can make more instances, if required.

你可以下载 Zope 3.1.0 或以后的版本。作为根用户安装 Zope3,虽然并不需要这样做。当你用 Zope3 来做实验时,可以做为一个普通用户来创建实例。而对于产品系统而言,你可以从操作系统的安全等级中得到额外的好处。由于我们手动安装 Zope3 (作为根用户),所以缺省的安装路径将是 /usr/local/Zope-3.1.x。当生成 Zope 实例时,你必须要指定 Zope 的管理用户名和密码。如果需要的话,你可以生成更多的实例。

In your Zope 3 instance directory, there are few directories with specific purposes. Here ownwards I will be using $ZOPE3INSTANCE to refer your instance directory

在你的 Zope 3 实例目录中,有一些指定用途的目录。在这样,我将使用 $ZOPE3INSTANCE 来代表你的实例目录

$ZOPE3INSTANCE/etc In 'etc' you can see some configuration files. In $ZOPE3INSTANCE/etc/zope.conf you can edit port numbers of http and ftp servers.

在 'etc' 中你可以看到一些配置文件。在 $ZOPE3INSTANCE/etc/zope.conf 文件中你可以编辑 http 服务和 ftp 服务的端口号。

$ZOPE3INSTANCE/var Zope saving all data here. Backup this directory regulary. If 'Data.fs' is missing, it will be automatically created when you run zope again.

Zope 将所有数据保存在这里。定期备份该目录。如果 'Data.fs' 文件丢失的话,它会在你再次运行 Zope 时被自动创建。

$ZOPE3INSTANCE/bin Few utility scripts. 'runzope' and 'test' are already familiar to you. 'pyskel' script will be very useful for creating template codes from interfaces, Example:

一些工具脚本。 'runzope' 和 'test' 已经被你所熟知。'pyskel' 脚本对于从接口创建模板代码也是非常有用的。如:

$ $ZOPE3INSTANCE/bin/pyskel boom.interfaces.IMark > file.py

$ZOPE3INSTANCE/lib/python As I said earlier you can place your Zope3 packages here. By default this won't be in your Python path. You can also place your package in any standard Python path.

正如我先前所说,你可以将你的 Zope3 包放在这里。缺省状态下,它不会在你的 Python 目录里。你也可以将你的包放在任何标准的 Python 目录中。

Anchor(whycode)

Why should I code like this?(为什么我要这样编写代码呢?)

When we started discussing BookMarker, the first word I coined is Extreme Programming (XP). I strongly recommend you to read about Extreme Programming. It will really influence you to write code in Zope3 way (directly and indirectly). Ok, one causion: many XPers believe that frameworks are bad. Here, I can not give an answer in one sentence, so you find out yourself. "Extreme Programming Explained" by Kent Beck will be a good starting point for your study. By the way, another classic book which you can read is "Design Patterns" by Gang of Four. In this book they say : 'Program to an interface, not to an implementation'. To simulate a formal definition of interfaces in C++, they used classes with virtual functions. Just like this, in Python we will use zope.interface.Interfce inherited metaclass for defining an interface. There is every chance for an 'interface' concept in Python language by version 3.0 . According to Extreme Programming: 'The four basic activities of development are coding, testing, listening, and designing.' Zope3 makes your software testing, a breeze. You can write unit and functional tests very easily.

当我们开始讨论书签时,我提出的第一个词是极限编程(XP),我强烈推荐你去看看极限编程的相关内容。它能够真正改变你,让你用 Zope3 的方式去编写代码(直接或间接)。OK,一个原因:许多极限编程人员都相信框架是不好的。在这里,我不能用一句话来回答,因此你可以自已去找出答案。 Kent Beck的《极限编程说明》对你学习极限编程来说将是一个好的起点。另外,另一本你可以看的经典书籍就是 Gang of Four 的《设计模式》。在这本书中他们提到:“程序是一个接口,而不是一个实现”。与 C++ 中接口的形式定义相同,他们用类来虚拟函数。为此,在 Python 中我们为定义一个接口可以用 zope.interface.Interfce 来继承元类。There is every chance for an 'interface' concept in Python language by version 3.0 . 根据极限编程的说法:“开发的四个基本活动就是编码,测试,监听和设计” Zope3 可以轻易地测试你的软件。你可以非常容易地编写单元测试和功能测试。

Anchor(lookinto)

Let's look into interfaces(让我们研究接口)

I hope you are familiar with the concept of interfaces. Anyway, when we speak about an interface, we meant it to use with reference to an object (i.e, an instance of a class). For example if 'A' is a class which implements 'IA', and 'a' is an instance of 'A', then 'IA' is the interface of 'a', got it? But normally we only deals with the interface and its implementing class.

我希望你熟悉接口的概念。无论如何,当我们讲到接口时,我们的意思就是引用一个对象(如一个类的实例)。举个例子,如果“A”是一个类,实现了“IA”,“a”是“A”的一个实例,那么“IA”就是“a”的接口,明白吗?但通常我们只讨论接口和实现它的类。

In our interfaces.py we defined three interfaces. The first interface 'IMark' defines a book mark object. A book mark has two attributes, one is the url and another one is the description. We used schemas available at zope.schema package to specify these attributes.

在我们的 interfaces.py 文件中,我们定义了三个接口。第一个接口“IMark”定义了一个书签对象。一个书签有两个属性,一个是 url 而另一个是 描述。我们使zope.schema 包中的 schemas 有效,以指定这些属性。

As we mentioned earlier IBookMarker is a container interface. We extended IContainer interface with one name attribute. Also we put one item type pre-condition. So IBookMarker object can only contain an IMark object. Now before moving to the next section, please note from which packages and modules we imported different classes/interfaces. Just open the sources of those packages, and see how well documented they are!. Some documentation are written in seperate ReStructuredText files with unit testing, this is the Zope3 way of unit testing.

正如我们先前提到的,!IBookMarker是一个容器接口。我们扩展了带一个名字属性的 IContainer 接口。我们放入一个类型为 pre-condition 的项。因此 IBookMarker 对象就只能包含一个 IMark 对象了。在进入下一节之前,请注意我们从哪个包和模块中导入不同的类/接口。打开这些包的源代码,看看它们多么适当地被证实。一些文档被写在带单元测试的 seperate ReStructuredText 文件中,这些都是 Zope3 方式的单元测试方法。

Anchor(revisit)

Unit testing re-visited(再看看单元测试)

We wrote our test in a file named tests.py. You can also write tests in a package named tests. All test modules under this package should have test_ prefix. We also automated our doctests written along with implementation. To test our !BookMarker container, we inherited TestSampleContainer. For testing containers, you can stick with unittest module. Also use it where you want more reusablity. Anyway, we will integrate all doctests with unittest module. This will help us to run tests automatically, from a single point.

我们在文件 tests.py 中编写我们的测试。你也可以在 tests 包中编写测试。所有在该包中的测试模块将有一个 test_ 的前缀。我们也与实现一起自动进行我们的 doctests。为了测试我们的 !BookMarker 容器,我们继承了 TestSampleContainer。为了测试 containers,你可以加入 unittest 模块。你也可以在你其他需要重用的地方使用它。无论如何,我们将用 unittest 模块集成所有的 doctests。这将帮助我们从单一的点开始自动进行测试。

Anchor(talkabout)

Let's talk about implementations(让我们讨论下实现)

In the first line of bookmarker.py we set a special variable attribute <u>docformat</u> = 'restructuredtext'. Our documentation strings are written in ReStructuredText format. I strongly reccomend you to use ReST for all kinds of Python documentations. (This article is written in ReST: svn co svn://svn.berlios.de/zissue/trunk/z3in30m).

在 bookmarker.py 文件的第一行,我们设置了一个特殊的可变属性 <u>docformat</u> = 'restructuredtext'。我们的文档字符串是用 ReStructuredText 格式写的。我强烈建议你在 Python 所有类型文档中都用 ReST。(本文的 ReST 格式在:svn co svn://svn.berlios.de/zissue/trunk/z3in30m)

First we imported implements function from zope.interface package. Using this function we can say a class implements one or more interfaces. BTreeContainer is full implementation of IContainer interface. We inherit it to implement our Container interfaces. Similarly Contained is an implementation of IContained. Mark class implements both IMark and !IMarkContained. IMarkContained is an extended interface of IContained. So by inheriting Contained class we get a partial implementation of our interfaces. Now the remaining things to implement is two attributes, url and description. Similarly majority of IBookMarker is implemented in !BTreeContainer. I hope documentation strings are self explanatory.

首先我们从 zope.interface 包中导入实现函数。使用该函数,我们可以说一个类实现一个或更多的接口。BTreeContainer 是 IContainer 接口的完全实现。我们继承它以实现我们的 Container 接口。同样 Contained 是 IContained 的实现。Mark 类实现 IMark 和 IMarkContainedIMarkContained 是 IContained 的一个扩展。因此通过继承 Contained 类,我们得到了我们接口的部分实现。现在剩下来要实现的事就是两个属性,url和描述了。同样 IBookMarker 的大部分功能都在 BTreeContainer 中被实现。我希望文档字符串是可以自说明的。

Anchor(explain)

ZCML Explained(ZCML 说明)

Let me ask one question, which you are going to face many times later. Do you think a Programming language should be used to write configuration files? If yes, why?. Why we can not use a text files with some conventions or markups.

让我来问个问题,在这之后你常常打算面对什么。你认为编程语言应该被用来编写配置文件吗?如果是的话,为什么?为什么我们不能用有着一些约定或标识的文本文件呢?

Anyway, ZCML is the XML based configuration system for Zope3. The base tag 'configure' specifies namespaces to use. In our configuration we used two namespaces, 'zope' and 'browser'. 'zope' namespace contains the basic elements required to register our content objects. 'browser' is for view related configuration.

无论如何,ZCML是 Zope3 中基于 XML 的配置系统。基本标识 “configure”指定所用的名称空间。在我们的配置中,我们使用两个名称空间,“zope”和“browser”。“zope”名称空间包括要求注册我们内容对象的基本元素,而“browser”则是用于与视图相关的配置。

The first tag we used is 'interface'. It is called a directive. In our configuration 'iterface' is a simple directive and 'content' is a complex directive.

我们用的第一个标识是“interface”。这被称为一个语句。在我们的配置中,'iterface'是一个简单语句,'content'是一个复合语句。

Anchor(zpt)

Views and ZPT(视图和 ZPT)

Your objects are finally saved in ZODB, you may choose other storage mechanisms also. In zope you can present your objects in different ways. I mean, through different protocols like http, ftp, xmlrpc etc. In our case, we created a view for browser (yes, through http). We put all logics for presentation in browser.py. And created a Zope Page Template (ZPT) for real presentation. Normally you should avoid any information retrieval logic in ZPT.

你的对象最终被保存在 ZODB中,你也可以选择其他保存机制。 在 zope 中你可以通过不同的方式来描述你的对象。我的意思是通过不同的协议如 http,ftp,xmlrpc等。在我们的示例中,我们为浏览器创建一个视图(是的,通过 http)。我们在 browser.py 文件中为表现放入所有的逻辑,并为真正的表现创建一个 Zope 页面模板(ZPT)。通常你应该避免在 ZPT 中放入任何逻辑信息。

Anchor(nomention)

The things we didn't mentioned(我们没有提及的事物)

Please go to the last section, otherwise you can not finish this article in 30 minutes Smile

请到最后一节,否则你不可能在30分钟之内看完这篇文章 Smile

Ofcourse, in an introductory document we can only cover a fraction of the whole technology. Here I have omitted many things for various reasons.

当然,在一篇介绍性文章中我们只能提及整个技术的一部分。这里由于各种原因我省略了很多东西。

In the beginning, I said just one assumptiion about you. I really meant many other things. Surely you should be a Python programmer. You should know basic administration. Basic understanding of web technologies. And ofcourse, willing to spend time Smile

在开始,对于你我只做了一个假定,其实我有很多其他的意思。确信你应该是一个Python程序员、你应该知道基本管理、基本理解 Web 技术,当然还有就是愿意花时间 :)

While installation you might get error due to Python development libraries not installed. If you know Python and system administration you will just run: apt-get install python-dev Similary you have created <u>init</u>.py file to make our package working.

在安装过程中,你也许会得到一个没有安装 Python 开发库的错误提示。如果你知道 Python 和系统管理权的话,你只需运行:apt-get install python-dev 就象你创建 <u>init</u>.py 文件用来运行你的包一样。

If you are interested in Zope3 by now, surely you will explore more in future. While you exploring, you will see that doctests can be written in stand alone text files. Similarly you will understand lots of other things.

如果你现在对 Zope3 感兴趣的话,确定你以后会进行更多的研究。在你研究过程中,你将发现 doctests 可以写在单独的文本文件中。同时你也会理解很多其他事物。

One thing I can assure you is that zope is really a matured framework. It has almost 9 year history of successfull running. Many technologies evolved through zope. Infact zope and zope developers has influenced Python language itself. Yes! it is one of the gratest Python application ever written.

我可以向你确保的就是 zope 是一个真正成熟的框架。它已经有 9 年成功运行的历史了。许多技术都是通过 zope 改善的。事实上 zope 和 zope 开发人员也影响了 Python 语言自身。是的,它是最伟大的 Python 应用之一。

Anchor(end)

The End(结束语)

Oh! it is just the end of this article. And the great beginning of your journey through Zope3 world. So, good luck. 哦!这只是这篇文章的结束,却是你在 Zope3 世界旅程的开始。那么,祝你好运!

Anchor(about)

About the author(关于作者)

I am Python programmer from Kerala. I love Python. Previously I have worked for Malayalam i18n & l10n in free softwares. I have worked for Free Software Foundation of India (as a job). I was a Koha consultant for some time. Currently I am doing lots of Python, PyGTK and PostgreSQL (about one and half years). I am a prod GNU Emacs user. 我是来自 Kerala 的 Python 编程人员。我热爱 Python。 以前我致力于实现自由软件中 Malayalam语 的 i18n & l10n 化。我也为印度自由软件基金会工作(作为一份工作),有段时间我是 Koha 的顾问。当前我用 Python,PyGTK 和 PostgreSQL 做了很多事(大约有一年半的时间)。我是一个 GNU Emacs 用户。