Personal tools
You are here: Home Zope Tutorials 30分钟学会zope3 你的第一个Zope3应用

你的第一个Zope3应用

Document Actions
开始编写第一个zope3应用

panjy

本文由firehare等翻译。 http://zissue.berlios.de/z3/Zope3In30Minutes.html
Page 2 of 4.

你的第一个Zope3应用

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

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

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

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

接口

下面就是我们的interfaces.py:

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):
    """这是书签对象."""

    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):
    """这是所有书签对象的容器."""

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

    def __setitem__(name, obj):
        pass

    __setitem__.precondition = ItemTypePrecondition(IMark)


class IMarkContained(IContained):
    """一条书签只能包含在一个BookMarker容器中"""

    __parent__ = Field(
        constraint = ContainerTypesConstraint(IBookMarker))

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

单元测试

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

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 __name__ == '__main__':
    unittest.main(defaultTest='test_suite')

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

然后运行单元测试:

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

正式编码

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

__docformat__ = '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):
    """IMark的实现

    确认`Mark` 实现了`IMark` 接口::

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

    确认`Mark` 实现了`IMarkContained`接口:

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

    一个检查Mark的链接地址的示例::

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

    检查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):
    """使用B-Tree容器来实现IBookMarker接口

    确认`BookMarker` 实现了`IBookMarker` 接口::

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

    改变书签名字的示例::

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

    implements(IBookMarker)

    name = u""

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

配置

现在编写配置(保存在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>

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

开始运行吧

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

<include package="boom"/>

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

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

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

by 潘俊勇 last modified 2005-10-15 01:49
Contributors: Author: Baiju M <baiju.m.mail AT gmail.com>, 翻译:firehare, 校正:leal, 组织:ubuntu.org.cn

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: