23.1 步骤 I: 创建 XML-RPC 表示组件方法
Obviously we have to create a view component for both content objects, MessageBoard and Message. However, both share the functionality that they can contain and manage sub-messages, so that it is desired to factor out this functionality into a common base class, MessageContainerMethods. Since we want to keep the XML-RPC code separate, create a new module called xmlrpc.py in the messageboard directory and add the following content:
显然我们必须为内容对象 MessageBoard 和 Message 创建视图组件。然而,由于两者共有的功能是它们可以包含和管理子消息,因此,要将该功能分离出来放在一个公共的基类 MessageContainerMethods 中。因为我们想保持 XML-RPC 代码的独立性,因此在消息栏文件夹中新建一个名为 xmlrpc.py 的模块,并添加下列内容:
代码: 全选
1 from zope.event import notify
2 from zope.app.publisher.xmlrpc import MethodPublisher
3
4 from zope.app.event.objectevent import ObjectCreatedEvent
5
6 from book.messageboard.message import Message
7
8 class MessageContainerMethods(MethodPublisher):
9
10 def getMessageNames(self):
11 """Get a list of all messages."""
12 return list(self.context.keys())
13
14 def addMessage(self, name, title, body):
15 """Add a message."""
16 msg = Message()
17 msg.title = title
18 msg.body = body
19 notify(ObjectCreatedEvent?(msg))
20 self.context[name]? = msg
21 return name
22
23 def deleteMessage(self, name):
24 """Delete a message. Return True, if successful."""
25 self.context.__delitem__(name)
26 return True
* 第 8 行: 生成一个 MethodPublisher 类,它与 BrowserView 相似且它的构造函数需要一个上下文对象和一个 XMLRPCRequest 实例。
* Line 10-12: Return a list of all message names. But remember, we implemented the containment with BTrees (see first chapter of this part), so that keys() will not return a list or tuple as a result, but a btree-items object. Therefore we need to implicitly cast the result to become a list, so that XML-RPC is able understand it.
* 第 10-12 行: 返回所有消息名列表。但请记住,我们实现与 BTrees 的包容(参见本部分的第一章),因此 key() 不能返回列表或元组作为结果,除了 btree-item 对象。因此我们需要将结果变成一个列表,以便 XML-RPC 能够明白它。
* Line 19: Since we want to play nice with the system, let it know that we created a new content object.
* 第 19 行: 因为我们想让系统运行良好,想让它知道我们已经新建了一个内容对象。
* Line 21, 26: Make sure we return something, so that XML-RPC will not be upset with us. As mentioned before, if no return value is specifed, None is implicitly returned, which XML-RPC does nto understand.
* 第 21, 26 行: 保确我们能返回数据,以便 XML-RPC 不会混乱。如前面所讲,如果没有指定返回值则 None 会被缺省返回,而 XML-RPC 是不能明白的。
The two actual views for our content objects are now also implementing accessor and mutator methods for their properties. So here are the two views:
内容对象的两个真实视图现在也实现了 accessor 和 mutator 方法
代码: 全选
1 from zope.app.event.objectevent import ObjectModifiedEvent
2
3 class MessageMethods(MessageContainerMethods):
4
5 def getTitle(self):
6 return self.context.title
7
8 def setTitle(self, title):
9 self.context.title = title
10 notify(ObjectModifiedEvent(self.context))
11 return True
12
13 def getBody(self):
14 return self.context.body
15
16 def setBody(self, body):
17 self.context.body = body
18 notify(ObjectModifiedEvent(self.context))
19 return True
20
21
22 class MessageBoardMethods(MessageContainerMethods):
23
24 def getDescription(self):
25 return self.context.description
26
27 def setDescription(self, description):
28 self.context.description = description
29 notify(ObjectModifiedEvent(self.context))
30 return True
* 第 10, 18 & 29 行: 当修改消息栏或消息时,我们必须明确发出修改通知事件。直至目前我们也没必要处理这些,因为这些事件被浏览器表单的事件机制自动创建了。
* Line 11, 19 & 30: Again, we need to make sure we do not just return None from a method.
* 第 11, 19 & 30 行: 再一次,我们需要确保我们不能从方法中返回 None。
That’s already everything from a coding point of perspective. But before we hook up the code in the component architecture, we need to do some testing.
从编程的角度一切准备就绪。但在我们将代码放入组件架构之前,我们还需要做一些测试。