个人工具

Zope3宝典/改变尺寸信息

来自Ubuntu中文

跳转至: 导航, 搜索

Chapter 17: Changing Size Information(第 17 章:改变尺寸信息)


原文出处:The Zope 3 Developers Book - An Introduction for Python Programmers

原文作者:StephanRichter, zope.org

授权许可:创作共用协议

翻译人员:

校对人员:Leal, FireHare

适用版本:Zope 3

文章状态:校正阶段



Difficulty(难度)

Newcomer(初学者)

Skills(技能)

  • You should be familiar with the previous chapters of the “Content Components” section.
    您应该熟悉“内容组件”一章。

Problem/Task(问题/任务)

Currently, when looking at the contents view of a message, it will show you the amount of items in the message, which includes reply-messages and attachments (files and images). It would be nice if the size field would say “x replies, y attachments”.
现在,当然我们查看消息内容视图时,它将在消息里显示条目的数目,它包括回复消息和附件(文件和图像)。如果大小字段以“x- 回复, y- 附件”显示是一个不错的主意。


Solution(解决方案)

The size output is handled by a very simple adapter, which will adapt from IMessage to ISized.
一个非常简单的适配器来处理大小输出,该适配器ISized将由IMessage修改而成。

17.1 Step I: Implementation of the Adapter(17.1 步骤 I:适配器的实现)

An adapter is usually a simple class, which is marked by the fact that it takes one object as constructor argument. This object must provide the “from” interface that is often also listed in the `used_for` attribute of the class. Add the following code in your message.py file:
一个适配器通常是一个简单的类, 它把一个对象当作一个构造函数参数。这个类必须提供"from" 接口,该接口也经常在该类 `used_for` 属性中被列出。在您的message.py文件中添加如下代码:

#!python
from zope.app.size.interfaces import ISized

class MessageSized(object):

implements(ISized)
<u>used_for</u> = IMessage

def <u>init</u>(self, message):
self._message = message

def sizeForSorting(self):
"""See ISized"""
return ('item', len(self._message))
def sizeForDisplay(self):
"""See ISized"""
messages = 0
for obj in self._message.values():
if IMessage.providedBy(obj):
messages += 1

attachments = len(self._message)-messages

if messages === 1: size == u'1 reply'
else: size = u'%i replies' %messages

if attachments == 1: size += u', 1 attachment'
else: size += u', %i attachments' %attachments

return size

The ISized interface specifies two methods:
ISized接口指定了两个方法:

  • Line 10-12: sizeForString() must return a tuple with the first element being a unit and the second the value. This format was chosen to provide a generic comparable representation of the size.
    第10-12行:sizeForString() 必须以第一个元素是单位(unit)和第二个是值(value)返回一个元组。选择提供一个通用的大小表示比较的格式。
  • Line 14-29: sizeForDisplay() can return any sort of unicode string that represents the size of the object in a meaningful way. The output should not be too long (mine is already very long). As promised it displays both responses and attachments separately.
    第14-19行:sizeForDisplay() 能返回表示该对象尺寸任何种类的unicode字符串。 输出不应该太长(我的已经很长)。正如我们承诺的分开显示回复和附件。

17.2 Step II: Unit tests(17.2 步骤 II:单元测试)

Now let’s write some doc tests for the adapter. Add the following tests In the doc string of the sizeForSorting() method:
现在让我们为适配器写一些doc测试。 把下列的测试代码加入到sizeForSorting() 的doc字符串方法:

1  Create the adapter first.
2  
3  >>> size = MessageSized(Message())
4  
5  Here are some examples of the expected output.
6  
7  >>> size.sizeForSorting()
8  ('item', 0)
9  >>> size._message['msg1'] = Message()
10  >>> size.sizeForSorting()
11  ('item', 1)
12  >>> size._message['att1'] = object()
13  >>> size.sizeForSorting()
14  ('item', 2)

The test is straight forward, since we add an object and check whether it increased the size of items by one. In the sizeForDisplay() doc string add:
由于我们添加了一个对象并且检查项目的大小是否增加。在sizeForDisplay() doc字符串添加:

1  Create the adapter first.
2  
3  >>> size = MessageSized(Message())
4  
5  Here are some examples of the expected output.
6  
7  >>> size.sizeForDisplay()
8  u'0 replies, 0 attachments'
9  >>> size._message['msg1'] = Message()
10  >>> size.sizeForDisplay()
11  u'1 reply, 0 attachments'
12  >>> size._message['msg2'] =  Message()
13  >>> size.sizeForDisplay()
14  u'2 replies, 0 attachments'
15  >>> size._message['att1'] = object()
16  >>> size.sizeForDisplay()
17  u'2 replies, 1 attachment'
18  >>> size._message['att2'] = object()
19  >>> size.sizeForDisplay()
20  u'2 replies, 2 attachments'

The doc tests are already registered, since the message.py file already contains some doc tests. However, adding an object to a container requires some of the component architecture to be up and running. There exists a testing convenience module called zope.app.tests.placelesssetup, which contains two functions setUp() and tearDown() that can be passed in the doc test suite as positional arguments. therefore the test suite declaration changes from
doc测试已经被注册,由于message.py文件已经包含了一些doc测试。然而,把一个对象加入一个容器需要一些结构组件运行在上面。这儿有一个叫zope.app.tests.placelesssetup便利的测试模块,它包含了能以位置参数传递到doc测试套件的两个函数:setUp()和tearDown()。因此,这些测试套件声明需要做些改变:

1  DocTestSuite('book.messageboard.message')

to
变成

1  DocTestSuite('book.messageboard.message',
2               setUp=setUp, tearDown=tearDown)

You can now run the tests the usual way.
您现在可以用通常的方式运行测试:

1  python2.3 test.py -vpu --dir src/book/messageboard

17.3 Step III: Registration(17.3 步骤 III:注册)

Now we register the adapter in messageboard/configure.zcml using the following ZCML directive:
现在我们使用下面的ZCML指令在messageboard/configure.zcml中注册适配器:

1  <adapter
2      factory=".message.MessageSized"
3      provides="zope.app.size.interfaces.ISized"
4      for=".interfaces.IMessage"
5      />

The zope:adapter is the way to register global adapters via ZCML. The factory attribute allows you to specify a list of factories (usually only one is specified) that are responsible for creating an adapter instance that takes an object implementing the interface specified in the for attribute and providing the interface specified in provides. All of these three attributes are mandatory.
zope:adapter是通过ZCML注册全局适配器的方法。工厂(factory)属性允许您指定一连串的工厂(通常只有一个被指定),专门负责创建适配器实例。在for属性里指定对象实现的接口,在provides里指定提供的接口。所有这三个属性都是强制性的。

For our case, we basically say that an instance of the `MessageSized` class provides an ISized interface for objects implementing IMessage.
对于我们的范例,我们基本上说 `MessageSized` 类的实例提供一个 ISized 接口给实现 IMessage 的对象。

The directive also supports two optional arguments. We can also specify a permission. The adapter will be only available to the principal, if the principal has the specified permission. If no permission is specified, everyone can access the adapter. The other optional argument of the directive is the name attribute that specifies the name of the adapter. Using names, we can specify multiple adapters from one interface to another.
指令也支持两个可选择的参数。我们也能指定一个许可。如果主体已经指定了许可,适配器将只对主体可用。如果没有许可指定,每个人都能访问该适配器。指令的其它可选参数是name属性,该属性指定了适配器的名称。使用名称,我们能从一个接口到另一个接口指定多个适配器。

That’s it! Restart Zope 3 and see for yourself. Note how we did not need to touch any existing Python code to provide this functionality.
这就是本章所有的内容了。重新启动Zope 3 并且自个儿瞧瞧。 注意我们不需要接触任何已经存在的Python代码就可以提供这些功能了。

Exercises(练习)

      • Write an ISized adapter for `IMessageBoard` that outputs xmessages as the displayable size.
        为 `IMessageBoard` 写一个 ISized 适配器输出xmessages(显示大小)。