r187 - doc/plonebook/trunk

2 views
Skip to first unread message

czug-checkins

unread,
Jun 19, 2006, 5:10:47 AM6/19/06
to czug-c...@googlegroups.com
Author: panjy
Date: Mon Jun 19 17:10:47 2006
New Revision: 187

Added:
doc/plonebook/trunk/plone-api-samples.rst
Modified:
doc/plonebook/trunk/chmconf.py

Log:
added plone-api section from czug.org


Modified: doc/plonebook/trunk/chmconf.py
==============================================================================
--- doc/plonebook/trunk/chmconf.py (original)
+++ doc/plonebook/trunk/chmconf.py Mon Jun 19 17:10:47 2006
@@ -18,6 +18,7 @@
'063-zpt-comment.rst',
'070-custom-skin.rst',
'071-old-custom-skin.rst',
+'plone-api-samples.rst',
'080-manage-workflow.rst',
'090-manage-security.rst',
'100-integration.rst',

Added: doc/plonebook/trunk/plone-api-samples.rst
==============================================================================
--- (empty file)
+++ doc/plonebook/trunk/plone-api-samples.rst Mon Jun 19 17:10:47 2006
@@ -0,0 +1,330 @@
+======================
+Plone 开发接口(API)
+======================
+
+:中文翻译: 柯铁军
+
+本文是关于Plone的API应用的简单介绍,作者Emanuel Sartor(ema...@menttes.com),翻译Natalia B. Bidart(nbi...@except.com.ar)
+
+英文原版: http://www.ifpeople.net/fairsource/courses/material/apiPlone_en
+
+.. Contents:: 内容
+.. sectnum::
+
+介绍
+-----------
+本文档描述了如何通过Plone/Zope的API来使用Plone中的对象。
+
+我们经常通过Python脚本来操作Plone中的对象。学习使用Plone/Zope的API,可以达到以下目的:
+
+* 控制content对象.
+* 使用Plone的catalog.
+* 控制用户和组.
+
+控制content对象
+----------------------------
+创建、删除、修改content对象的脚本样例。
+
+content对象,是指能够在Plone界面中添加的那些对象,比如页面、图片、链接、文件夹、新闻和文件。
+
+content对象可以通过Python脚本来操纵。换句话说,content对象可以被创建、修改和删除;它的状态也可以修改,对象所拥有的信息也能访问。
+
+例1:如何通过Python脚本访问content对象
+++++++++++++++++++++++++++++++++++++++++++++++++
+首先,通过Plone界面创建一个content对象。然后,我们根据下面步骤来通过一个脚本对它进行访问。
+
+* 添加一个document(Page),id取名为my_document.在Plone2.1.1中,这一步稍有不同,因为page的添加表单只要求page的title,所以取名My Document(id会自动生成)。
+
+* 从ZMI界面转移到你的Plone站点的文件夹下面,在其中的portal_skins/custom中,添加一个脚本(Script (Python)),其中内容如下::
+
+ from Products.CMFCore.utils import getToolByName
+
+ urltool = getToolByName(context, "portal_url")
+ portal = urltool.getPortalObject()
+ document = getattr(portal, "my_document")
+ print document.Title()
+ print document.CookedBody()
+ return printed
+
+在上面的例子中,可以看到getToolByName和getattr两个函数以及getPortalObject、Title和CookedBody三个方法的使用。更深一层:
+
+* ``getToolByName(obj, name, default=[])``
+
+ 这个函数是从CMF模块中导入的. 通过给定的name和obj返回tool。
+* ``getattr(object, name[, default])``
+
+ 是zope中的函数,它返回object指定属性名字的值。其中属性的名字必须是string类型。如果该对象没有属性与给定的名字相符,就会触发一个AttributeError,除非设定了第三个可选的参数。
+* ``hasattr(object,name)``
+
+ 是zope中的函数,如果参数name字符串是指定对象object的属性,该函数就返回True,否则返回False。
+* ``getPortalObject(self)``
+
+ 是从Products.CMFCore.URLTool.URLTool导入的类的方法。它返回Portal对象.
+
+例2:如何使用Python脚本修改一个document的内容
++++++++++++++++++++++++++++++++++++++++++++++++++
+通过修改例1中的脚本即可实现, 在print块中加这么一句话::
+
+ document.edit(text_format="html",
+ text="<div><b>This is a new text...</b></div>")
+
+edit方法使用如下:
+
+* ``edit(self, text_format, text, file="", safety_belt="")``
+
+ 方法属于CMFDefaults.Document.Document类.其中参数text_format可以是html, structured-text或是plain格式. 参数text是文档的body内容.
+
+例3:如何通过Python脚本复制和粘贴content对象
++++++++++++++++++++++++++++++++++++++++++++++++++
+* 创建一个文件夹,其id为my_folder. 注意这个操作过程在Plone2.1.1中稍有不同(Plone2.1.1中只须新文件夹的名字)
+* 下面的脚本,其功能是把刚才创建的my_document文档复制到新文件夹my_folder里::
+
+ from Products.CMFCore.utils import getToolByName
+
+ urltool = getToolByName(context, "portal_url")
+ portal = urltool.getPortalObject()
+ cb_copy_data = portal.manage_copyObjects(["my_document"])
+ folder = getattr(portal, "my_folder")
+ folder.manage_pasteObjects(cb_copy_data)
+
+现在,应该能了解如何使用这两个(三个)重要的方法:
+
+* ``manage_copyObjects(self, ids=None, REQUEST=None,RESPONSE=None)``
+
+ 从OFS.CopySupport.CopyContainer类中导入的.对对象进行引用,这些对象由粘贴面板中的id列表识别。
+* ``manage_cutObjects(self, ids=None, REQUEST=None)``
+
+ 方法同上
+* ``manage_pasteObjects(self, cb_copy_data=None, REQUEST=None)``
+
+ 从OFS.CopySupport.CopyContainer类中导入的.它将参数cb_copy_data所引用的对象进行粘贴,这个对象不是manage_copyObjects方法就是manage_cutObjects方法执行后的结果。
+
+例4:如何通过Python脚本删除centent对象
+++++++++++++++++++++++++++++++++++++++++++++++++
+下面的脚本将删除例1中创建的文档::
+
+ from Products.CMFCore.utils import getToolByName
+
+ urltool = getToolByName(context, "portal_url")
+ portal = urltool.getPortalObject()
+ portal.manage_delObjects(["my_document"])
+
+该例中manage_delObjects是一个关键方法:
+
+* manage_delObjects(self, ids=[],REQUEST=None)
+
+ 从CMFPlone.PloneFolder.BasePloneFolder类中导入.该方法删除id列表中id所指的所有对象。
+
+例5:如何通过Python脚本创建文档、文件和事件.
+++++++++++++++++++++++++++++++++++++++++++++++++
+思考下面的脚本::
+
+ from Products.CMFCore.utils import getToolByName
+ urltool = getToolByName(context, "portal_url")
+ catalogtool = getToolByName(context, "portal_catalog")
+ portal = urltool.getPortalObject()
+ #创建一个文档
+ doc = portal.invokeFactory("Document", "test_doc")
+ document = getattr(portal, "test_doc")
+ #document.setTitle("Test document")
+ #document.setDescription("This is the description of a test document")
+ document.editMetadata(title="Test document",
+ description="This is the description of a test document",
+ subject="")
+ document.edit(text_format="html",
+ text="<b>This is a test document!<b>")
+ #创建一个文件夹
+ fld = portal.invokeFactory("Folder", "test_folder")
+ folder = getattr(portal, "test_folder")
+ folder.setTitle("My Folder")
+ folder.setDescription("This is the description of a test folder")
+ catalogtool.refreshCatalog()
+ #创建一个事件
+ evt = folder.invokeFactory("Event", id="event")
+ event = getattr(folder, "event")
+ event.edit(title = "Foo",
+ start_date="2003-09-18",
+ end_date="2003-09-19",
+ location="home",
+ description="This is the description of a test event")
+ event.editMetadata(subject="Appointment")
+
+接下来对上面例子中使用到的一些方法进行解释说明:
+
+* ``editMetadata(self, obj, allowDiscussion=None, title=None, subject=None, description=None, contributors=None, effective_date=None, expiration_date=None, format=None, language=None, rights=None, **kwargs)``
+
+ 此方法定义在CMFPlone.PloneTool.PloneTool类中.
+* ``invokeFactory(self, type_name, id, RESPONSE=None, args, *kw)``
+
+ 参数type_name将要创建的内容类型的名字.
+
+ 需要注意的是,函数中的参数id必须和portal_types中的一样(但有可能和Plone用户界面中显示的类型名字不一样).参数id是新对象的标识(简称):这个名字在以后生成URL地址用得着.这个方法还接受其它一些参数,这些参数是传递到对象的构造方法中的.其中最普遍的就是title参数.
+* ``refreshCatalog(self, clear=0)``
+
+ 此方法对自身所包含的所有对象重新进行索引.
+
+例6:如何通过Python脚本改变私有文档的状态
+++++++++++++++++++++++++++++++++++++++++++++++
+看下面的例子::
+
+ from Products.CMFCore.utils import getToolByName
+ urltool = getToolByName(context, "portal_url")
+ portal = urltool.getPortalObject()
+ document = getattr(portal, "my_document")
+ review_state = document.portal_workflow.getInfoFor(document, "review_state", "")
+ print "The initial state is: " + review_state + "\n"
+
+ if not review_state in ("rejected", "retracted", "private"):
+ document.portal_workflow.doActionFor(document, "hide", comment="")
+ review_state = document.portal_workflow.getInfoFor(document, "review_state", "")
+ print "The final state is: " + review_state + "\n"
+ return printed
+
+其中有两个需要注意的方法:
+
+* ``getInfoFor(self, ob, name, default=[], wf_id=None, args,*kw)``
+
+ 这个方法从CMFCore.WorkflowTool.WorkflowTool类中导入.它返回与指定对象obj工作流相关的一个特别属性(由参数name指定).
+* ``doActionFor(self, ob, action, wf_id=None, args,*kw)``
+
+ 此方法从CMFCore.WorkflowTool.WorkflowTool类中导入.它基于指定对象obj的工作流而执行一个行为.
+
+使用Plone的catalog
+----------------------------
+Plone提供了一个叫Catalog的工具,可以在指定的Portal里搜索有关内容对象。
+
+这一节开始学searchResults方法使用。首先,先介绍其使用方法,然后,举一个其通用的使用样例.
+
+* ``searchResults(self, REQUEST=None, **kw)``
+
+ 这个方法定义在CMFCore.CatalogTool.CatalogTool类中,它通过调用 ZCatalog.searchResults方法执行操作.为根据用户的权限显示相应结果需要传递特定的参数。这些参数定义了如何对catalog实例进行查询。查询可以是关键词、映射或是REQUEST对象的一部分(比如从一个HTML文档发过来的请求).这个目录查询的索引可以是关键字名字、映射的关键字或是record对象的一个属性。
+
+ - record对象的属性
+
+ + query: 可以是对象的序列,也可以是单值传递给索引进行查询(强制性的).
+ + operator: 当对值的序列进行查询时,指定查询结果的组合方法(可选,默认值:OR).值的范围:当关键字是索引和路径索引时是"AND,OR";文本索引时范围是" AND, OR, ANDNOT, NEAR".
+ + range: 在一个索引上定义搜索范围(optional, default: off).可选值: min、max以及minmax。对对象进行搜索时,传递给查询的值中有大有小,min指定搜索的值比其中最大值都大,而max指定搜索的值不能超过值中的最小值,minmax是二者的结合.
+ + level: 只用于路径索引.该属性指定了开始执行搜索的文件目录层次(可选,默认值: 0).
+
+例7:如何按id降序排列所有文档
+++++++++++++++++++++++++++++++++++
+下面的脚本将把当前Portal中的所有文档按其id降序列出来。注意其中的参数,portal_type限制内容对象的类型,而sort_on和sort_order则指定排序的依据以及排序的方式::
+
+ results = context.portal_catalog.searchResults(sort_on="id",
+ portal_type="Document",
+ sort_order="reverse")
+ print [i.getObject().id for i in results]
+ return printed
+
+在Plone2.1.1中,如果按title对结果进行排序,则调用searchResults时需要由原来的给参数sort_on设定值直接改为sortable_title参数(好像不需要赋值,自己猜的:-))
+
+还有一点需要注意,getObject方法是由catalog中的搜索结果调用的,因为目录搜索出来的对象并不是content对象本身,而是一个包含了catalog schema信息的一个小的brain。可能正如你所想的,getObject方法返回的结果才是真正的content对象。
+
+例8:如何列出所有含有单词"texto"的私有对象。
+++++++++++++++++++++++++++++++++++++++++++++++++
+每个content对象都定义了自己信息的哪部分可以参与搜索。参数SearchableText就是对每个对象的那部分信息进行查找的。而参数review_state则是用来根据对象的状态进行过滤::
+
+ results = context.portal_catalog.searchResults(SearchableText="texto",
+ review_state="private")
+ print [i.getObject().Title() for i in results]
+ return printed
+
+例9:如何列出这样一些对象,他们的创建日期晚于2005/11/30,而且创建者是用户admin。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+下面的脚本说明了如何把一个record对象传递给searchResults方法。参数Date接受一record对象,并按其中给定的日期查找创建时间在其之后的那些对象。参数Creator则过滤掉那些不是由用户admin创建的对象::
+
+ results = context.portal_catalog.searchResults
+ (Date={"query": DateTime("2005/11/30"), "range": "min"},
+ Creator="admin")
+ print [i.getObject().Title() for i in results]
+ return printed
+
+控制用户和组
+---------------------------
+这一节里,讲述了如何使用Plone的API来创建用户和组,以及如何把用户分配到某个组里。
+
+例10:如何添加一个用户.
++++++++++++++++++++++++++++++++++
+看下面的代码::
+
+ id = "user"
+ fullname = "Emanuel Sartor"
+ password = "changeme"
+ email = "eman...@menttes.com"
+ roles = ("Manager",)
+ status=""
+ props = {"username": id,
+ "fullname": fullname,
+ "password": password,
+ "email": email}
+ # 在Portal中添加一个新成员
+ try:
+ context.portal_registration.addMember(id, password, roles,domains="",
+ properties=props)
+ status+="The user "+fullname+" was successfully added.\n"
+ except:
+ status+="The user "+fullname+" was not added.\n"
+ print status
+ return printed
+
+* ``addMember(self, id, password, roles, domains,properties)``
+
+ 这个方法用来创建一个PortalMember。
+
+更多信息请看 `RegistrationTool-class.html <http://api.plone.org/Plone/2.1.1/public/CMFPlone.RegistrationTool.RegistrationTool-class.html>`__
+
+例11:如何创建一用户组,取名Group0.
+++++++++++++++++++++++++++++++++++++++++
+看下面的代码::
+
+ groupname = "Group0"
+ status=""
+ # 添加一新租
+ try:
+ context.portal_groups.addGroup(groupname,)
+ status += "The group was successfully added.\n"
+ except:
+ status += "Manager group couldn't be added\n"
+ print status
+ return printed
+
+* ``addGroup(self, id, roles, groups, args, *kw)``
+
+ 更多信息请看 `GroupsTool-class.html <http://api.plone.org/Plone/2.1.1/public/CMFPlone.GroupsTool.GroupsTool-class.html>`__
+
+例12:如何向某个组里添加用户
++++++++++++++++++++++++++++++++++++++
+看下面的代码::
+
+ id = "usuario"
+ groupname = "Group0"
+ status=""
+ # 将用户user添加到groupname组
+ try:
+ group = context.portal_groups.getGroupById(groupname)
+ group.addMember(id)
+ status += "The user "+id+" was successfully added to "+groupname+".\n"
+ except:
+ status += "The user "+id+" was not added to group "+groupname+".\n"
+ print status
+ return printed
+
+练习
+-------------
+练习1:
+++++++++++
+编写一个脚本实现如下功能:脚本接受两个字符串变量doc1和doc2,并假设这两个参数对应当前文件夹下的两个文档标识。脚本能修改doc2的内容,使其变为doc1和doc2两个文档内容的连接。
+
+练习2:
++++++++++++
+编写一脚本实现如下功能:
+
+* 在plone的portal的根目录下创建一文件夹,题目为Events.
+* 将所有portal的Event类型对象移动到刚才创建的文件夹.
+* 把刚才portal的所有event对象状态修改为Published.
+
+提示:
+
+* obj.aq_inner.aq_parent是obj的父对象.
+* obj.objectValues()显示obj所有的孩子.
+

Reply all
Reply to author
Forward
0 new messages