Vous êtes sur la page 1sur 5

Plone API — ifPeople http://www.ifpeople.

net/fairsource/courses/material/apiPlone_en

Introduction

This document describes how Plone's objects can be manipulated by using Plone/Zope's API.

Very often, we'd like to manipulate Plone's objects by using scripts (Python). We are going to
learn how to use Plone/Zope's API in order to be able to:

Manipulate content objects.


Use Plone's catalog.
Manipulate users and groups.

Manipulate content objects

Script's examples to create, delete and modify content objects.

We call content objects to those objects that can be added through Plone's interface in order
to keep the portal's content: documents, images, links, folders, news and files.

The content objects can be manipulated by means of scripts written in Python. In other
words, content objects can be created, modified and deleted; its state can be modified, and
the information each object holds can be accessed.

Example 1: how to access a content object from a Python script.

First of all, let's create a content object through Plone's interface. Then, we're going to access
it from a script according to this steps:

Add a document (Page) with id my_document. This step is sightly different if we're
working under Plone 2.1.1 because the page's adding form only requests for the page's
title, in this case we write My Document (and the id gets automatically generated).
From ZMI, navigate trough your Plone Site's folder and go to portal_skins/custom.
There, add a script (Script (Python)) with the following content:

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

In the above example, we can see the use of getToolByName and getattr functions, and
getPortalObject, Title and CookedBody methods. Let's dig deeper:

getToolByName(obj, name, default=[]) It's imported from a CMF module. It returns


the tool given by name associated with obj.
getattr(object, name[, default]) Is a zope's function and it returns the attribute
name's value from object. name has to be a string. If object has no attribute named
name, an AttributeError exception is raised, except that the third (optional)
argument is set.
hasattr(object, name) Is a zope's function and it returns True if the string name is
the name of any attribute of object, False otherwise.
getPortalObject(self) This is a class method from
Products.CMFCore.URLTool.URLTool. It returns the Portal object.

Example 2: how to modify a document's content from a Python script.

This is done by modifying the script shown in example 1: we add a new sentence before the
print block:

document.edit(text_format="html",
text="<div><b>This is a new text...</b></div>")

edit method can be used according to the following:

edit(self, text_format, text, file="", safety_belt="") Method that belongs to


CMFDefaults.Document.Document class. text_format can be any of html,
structured-text, or plain. text is the document's body.

Example 3: how to copy and paste content objects from a Python script.

1 of 5 7/13/10 1:39 PM
Plone API — ifPeople http://www.ifpeople.net/fairsource/courses/material/apiPlone_en

Create a folder with id my_folder. Remember that this process is a little different if
working with Plone 2.1.1 (you only have to provie the new folder's name).
Below, a script tha copies the recently created document my_document into the new
folder '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)

Here, we can distinguish the use of two (three) important methods:

manage_copyObjects(self, ids=None, REQUEST=None, RESPONSE=None) Method


from OFS.CopySupport.CopyContainer class. It places a reference to the objects
identified by ids list inside the pasteboard.
manage_cutObjects(self, ids=None, REQUEST=None) Same as above.
manage_pasteObjects(self, cb_copy_data=None, REQUEST=None) Method from
OFS.CopySupport.CopyContainer class. It pastes the object referenced by
cb_copy_data, which has to be the result of either manage_copyObjects or
manage_cutObjects.

Example 4: how to delete a content object from a Python script.

The following script deletes the document created on example 1:

from Products.CMFCore.utils import getToolByName

urltool = getToolByName(context, "portal_url")


portal = urltool.getPortalObject()
portal.manage_delObjects(["my_document"])

manage_delObjects is the key method on this example:

manage_delObjects(self, ids=[], REQUEST=None) Method from


CMFPlone.PloneFolder.BasePloneFolder class. It deletes all elements which id
belongs to ids list.

Example 5: how to create a document, a folder and an event from a Python script.

Consider the following script:

from Products.CMFCore.utils import getToolByName


urltool = getToolByName(context, "portal_url")
catalogtool = getToolByName(context, "portal_catalog")
portal = urltool.getPortalObject()
# create a document
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>")
# create a folder
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()
# create an event
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")

Here, a few explanations about the methods used in the above example:

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)
Method defined in CMFPlone.PloneTool.PloneTool class.
invokeFactory(self, type_name, id, RESPONSE=None, args, *kw) type_name is
the name of the content type target for creation. Please note that this id has to be the
same as the one shown in the tool portal_types (but it might be different from the
type name shown in Plone's user interface). id is the identifier (short name) of the new
object: this name is used to later build the url. This method accepts some others

2 of 5 7/13/10 1:39 PM
Plone API — ifPeople http://www.ifpeople.net/fairsource/courses/material/apiPlone_en

parameters that are passed to the object's constructor method. One of the most
common is title.
refreshCatalog(self, clear=0) This methods reindexes all objects found inside self.

Example 6: how to change the state of a private document from a Python script.

Consider the following script:

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

We can observe the use of two methods:

getInfoFor(self, ob, name, default=[], wf_id=None, args, *kw) This is a


method from CMFCore.WorkflowTool.WorkflowTool class. It returns an specific
property (given by name) relative to a workflow for a given object ob.
doActionFor(self, ob, action, wf_id=None, args, *kw) Is a method from
CMFCore.WorkflowTool.WorkflowTool class. It executes the action over a workflow
for the given object ob.

Use Plone's catalog

Plone provides a tool (Catalog), that can be queried about content objects inside a given
Portal.

In this section we're going to learn the searchResults method. First, the use of it is going to
be explained, and secondly, an example of its common usage is going to be shown.

searchResults(self, REQUEST=None, **kw) This method is defined in


CMFCore.CatalogTool.CatalogTool class, and its implemented thourgh a call to
ZCatalog.searchResults method. Extra parameters are passed so results are limited
according to the user's permissions. The paremeters define the query to be made to the
catalog instance. The query can be a keyword, or a mapping, or part of a REQUEST
object (tipically from an HTML document). The index of the catalog to be consulted is
either the keyword's name, a mapping's key, or an attribute of a record object.
record objects' attributes
query: a sequence of objects or a single value to be passed as the query
to the index (mandatory).
operator: specifies the combination of search results when query is a
sequence of values (optional, default: OR). Possible values: AND, OR for
Keyword Indexes and Path Indexes; AND, OR, ANDNOT, NEAR for Text
Indexes.
range: defines a search range over an index (optional, default: off).
Possible values: min to search for object with larger values than the
maximun of the values passed in query, max same as min but searching for
smaller values than the minimun, and minmax which is a combination of
the formers.
level: only for Path indixes. It specifies the directory level in which start
the search (optional, default: 0).

Example 7: how to list all documents ordered decreasingly by id.

The following script lists all documents in the current Portal ordered decreasingly by id. Please
note that portal_type restrictes the type of the content objects, and sort_on and sort_order
specify the requerid ordering.

results = context.portal_catalog.searchResults(sort_on="id",
portal_type="Document",
sort_order="reverse")
print [i.getObject().id for i in results]
return printed

Under Plone 2.1.1, if we'd want to order results by title, we should make the searchResults
call setting sort_on parameter to sortable_title.

Please also note that the method getObject is called for each result obtained from the
catalog. This is because the objects resulting of a catalog search are not content objects
themself. As you migth guessed, getObject method returns the real content object.

3 of 5 7/13/10 1:39 PM
Plone API — ifPeople http://www.ifpeople.net/fairsource/courses/material/apiPlone_en

Example 8: how to list all private objects that include texto word.

Each content object defines what part of its information is searchable. The parameter
SearchableText searches for that information in every object. The parameter review_state
filters objects according its state:

results = context.portal_catalog.searchResults(SearchableText="texto",
review_state="private")
print [i.getObject().Title() for i in results]
return printed

Example 9: how to list all objects with creation date after November, 30th, 2005 and with
creation user admin.

This scripts shows how a record object can be passed to searchResults method. The Date
parameter receives a record object to query for those objects created after a given date. The
Creator parameter filters the objects that weren't created by admin user:

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

Manipulate users and groups

In this section we describe how to use the Plone's API to create users, groups, and how to
assign users to groups.

Example 10: how to add a user.

Consider the following:

id = "user"
fullname = "Emanuel Sartor"
password = "changeme"
email = "emanuel@menttes.com"
roles = ("Manager",)
status=""
props = {"username": id,
"fullname": fullname,
"password": password,
"email": email}
# add a new member to the 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) Creates an returns


a PortalMember.

More on RegistrationTool-class.html

Example 11: how to create a group named Group0.

Consider the following:

groupname = "Group0"
status=""
# add a new group
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)

More on GroupsTool-class.html

Example 12: how to add a user to a group.

Consider the following:

4 of 5 7/13/10 1:39 PM
Plone API — ifPeople http://www.ifpeople.net/fairsource/courses/material/apiPlone_en

id = "usuario"
groupname = "Group0"
status=""
# assign the user "user" to the group "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

Exercices

Exercice 1:

Codify an script that receives two string arguments doc1 and doc2, and assume that this two
parameters correspond to two document identifiers in the current folder. Make the script
modify the content of doc2 so it'll hold the concatenation of doc1 and 'doc2's content.

Exercice 2:

Codify an script that:

Creates a folder with title Events in plone portal's root.


Moves all portal's objects with type Event to the newly created folder.
Changes the state of all portal's event to Published.

Help:

obj.aq_inner.aq_parent is the object's parent of obj.


obj.objectValues() lists all obj's children.

5 of 5 7/13/10 1:39 PM

Vous aimerez peut-être aussi