Document Actions
Send this page to somebody Print this page
Parte 1

Instalar Clouseau y DocFinderTab en el sitio.

Tener en cuenta que las sesiones de Clouseau no llevan cuenta de los cambios que se vayan realizando en el sitio. Esto quiere decir que si hacemos un cambio en la interfaz Plone mientras tenemos abierta una sesión de Clouseau, estos cambios no estarán disponibles en la sesión. Para tener los cambios disponibles sólo tenemos que iniciar una nueva sesión de Clouseau.


Usando la interfaz Plone, crear página "Mi documento" y carpeta "Mi carpeta".

Ejemplo 1: acceder a un objeto de contenido desde un script.

  • Agregamos un documento (página) a nuestro sitio Plone cuyo identificador sea mi-documento. A partir de Plone 2.1 sólo escribimos el título Mi documento y el identificador se genera automáticamente, en Plone 2.0.x debemos escribir el identificador en el formulario de creación del documento.
  • A través del ZMI vamos a portal_skins/custom y agregamos un objeto Script (Python) cuyo contenido sea:
#Script python anda como está.
from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, 'portal_url')
portal = urltool.getPortalObject()

document = getattr(portal, 'mi-documento')
print document.Title()
print document.CookedBody()
return printed
#En Clouseau:
>>> page = getattr(portal, 'mi-documento')
>>> page.Title()
'Mi documento'
>>> page.CookedBody()
'\r\nEste es el cuerpo del documento.\r\n'

En el script se observa el uso de las funciones getToolByName y getattr, y de los métodos getPortalObject, Title y CookedBody. Veamos cómo se usa cada uno.

  • getToolByName(obj, name, default=[]) Se importa desde un módulo CMF. Devuelve la herramienta (tool) dada por name (string) dentro del objeto obj.
  • getattr(object, name) es una función de Python. Devuelve el valor del atributo nombrado de object. name tiene que ser string. Si name es uno de los atributos de object, el resultado es el valor de ese atributo. Por ejemplo, getattr(x, foobar) es equivalente a x.foobar. Si el atributo no existe, se devuelve default, de otra forma se lanza AttributeError.
  • hasattr(object, name) es una función de Zope.los argumentos son un objeto y un string. El resultado es 1 si el string es el nombre de alguno de los atributos del objeto, y es 0 en caso contrario. (Esto se implementa llamando a gettattr(object, name) y checando si lanza una excepción o no).
  • getPortalObject(self) es un método de la clase Products.CMFCore.URLTool.URLTool que devuelve el objeto Portal.

Ejemplo 2: modificar el contenido de un documento por medio de un script

Antes de las sentencias print en el script del ejemplo 1, agregamos:

from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, 'portal_url')
portal = urltool.getPortalObject()
document = getattr(portal, 'mi-documento')
document.setText('<b>Texto en negrita</b>')
print document.Title()
print document.CookedBody()
return printed

Desde Clouseau:

  >>> page = getattr(portal, 'mi-documento')
>>> page.setText('Lindo texto en negrita')
>>> import transaction
>>> transaction.commit()

Ejemplo 3: copiar y pegar objetos de contenido

  • Crear una carpeta con identificador mi-carpeta. Recordar que en Plone 2.1.1 basta con crear una carpeta con título Mi carpeta y que en Plone 2.0.x tendremos que escribir el identificador en el formulario de creación.
  • El script que se muestra abajo, copia el documento creado en el ejemplo 1 y lo pega dentro de la carpeta recientemente creada:

from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, 'portal_url')
portal = urltool.getPortalObject()
cb_copy_data = portal.manage_copyObjects(['mi-documento'])
folder = getattr(portal, 'mi-carpeta')
folder.manage_pasteObjects(cb_copy_data)

Este script no anda en Clouseau por problemas de permisos.

Aquí vemos la utilización de dos métodos: manage_copyObjects y manage_pasteObjects, ambos se explican a continuación junto con manage_cutObjects.

  • manage_copyObjects(self, ids=None, REQUEST=None, RESPONSE=None) es un método de la clase OFS.CopySupport.CopyContainer. Pone una referencia a los objetos nombrados en ids en el portapapeles.
  • manage_cutObjects(self, ids=None, REQUEST=None) es un método de la clase OFS.CopySupport.CopyContainer.Pone una referencia a los objetos nombrados en ids en el portapapeles.
  • manage_pasteObjects(self, cb_copy_data=None, REQUEST=None) es un método de la clase OFS.CopySupport.CopyContainer. Pega los objetos previamente copiados en el objeto actual. Si es llamado desde código Python, se debe pasar el resultado de una llamada previa a manage_cutObjects o manage_copyObjects como primer argumento.

Ejemplo 4: borrar un objeto de contenido.

El siguiete script borra el documento que creamos en el ejemplo 1:

  from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, 'portal_url')
portal = urltool.getPortalObject()
portal.manage_delObjects(['mi-documento'])

No anda en Clouseau por problemas de permisos.

Aquí usamos el método manage_delObjects que se explica a continuación.

  • manage_delObjects(self, ids=[], REQUEST=None) es un método de la clase CMFPlone.PloneFolder.BasePloneFolder. Elimina todos aquellos elementos cuyos identificadores aparezcan en ids.

Ejemplo 5: crear un documento, una carpeta y un evento desde un script.

 from Products.CMFCore.utils import getToolByName

urltool = getToolByName(context, 'portal_url')
catalogtool = getToolByName(context, 'portal_catalog')

portal = urltool.getPortalObject()

# Creando un documento
doc = portal.invokeFactory('Document', 'test-doc')
document = getattr(portal, 'test-doc')
#document.setTitle('Documento de prueba')
#document.setDescription('Esta es la descripción de un documentos de prueba')
document.editMetadata(title='Documento de prueba', description='Esta es una descripción', subject='')
document.edit(text_format='html', text='<b>Este es un dodumento de prueba</b>')

# Creando una carpeta
fld = portal.invokeFactory('Folder', 'test-folder')
folder = getattr(portal, 'test-folder')
folder.setTitle('Mi Carpeta')
folder.setDescription('Esta es la descripción de la carpeta.')
catalogtool.refreshCatalog()

# Creando un evento
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='Este es un evento de prueba.')
event.editMetadata(subject='Appointment')

* No probado en Clouseau.

  • 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) definido en la clase CMFPlone.PloneTool.PloneTool
  • invokeFactory(self, type_name, id, RESPONSE=None, args, *kw): type_name es el nombre del tipo de contenido que se quiere crear. Notar que este es el id del objeto que está en la herramienta portal_types, el cual puede no ser el mismo que aparece en la interfaz de usuario de Plone, la cual usa el título del tipo, si está disponible. id es el identificador (short name) del nuevo objeto, el que aparecerá en la URL. invokeFactory también acepta otros parámetros, los cuales se pasan al constructor del objeto, se pueden usar si se conoce el constructor; uno muy común es title.
  • refreshCatalog(self, clear=0) reindexa todos los objetos que encuentra.

Ejemplo 6: cambiar el estado de una carpeta de privado a público.

* Usar este script que cambia el estado de la carpeta "Mi carpeta" de privado a público:

from Products.CMFCore.utils import getToolByName
urltool = getToolByName(context, 'portal_url')
portal = urltool.getPortalObject()
folder = getattr(portal, 'mi-carpeta')
review_state = portal.portal_workflow.getInfoFor(folder, 'review_state', '')
print 'El estado inicial era: ' + review_state + '\n'
if not review_state in ('rejected', 'retracted', 'published'):
folder.portal_workflow.doActionFor(folder, 'publish', comment='')
review_state = portal.portal_workflow.getInfoFor(folder, 'review_state', '')
print 'El estado final es: ' + review_state + '\n'
return printed

* No anda en Clouseau por problemas de permisos.

En este script se observa el uso de dos métodos: getInfoFor y doActionFor, veamos en más detalle cada uno de ellos

  • getInfoFor(self, ob, name, default=[], wf_id=None, args, *kw) es un método de la clase CMFCore.WorkflowTool.WorkflowTool. Devuelve una propiedad específica (dada por name), relativa al workflow para un objeto ob.
  • doActionFor(self, ob, action, wf_id=None, args, *kw) es un método de la clase CMFCore.WorkflowTool.WorkflowTool. Ejecuta la acción de workflow dada por action para el objeto ob.

Usar el catálogo de Plone

Plone provee una herramienta, el catálogo, a la cuál se le puede consultar sobre los objetos de contenido dentro del portal.

En esta sección veremos el uso del método searchResults, inicialmente se describirá el uso de la misma y posteriormente veremos ejemplos de su uso.

El método searchResults(self, REQUEST=None, **kw)

Este método está definido en CMFCore.CatalogTool.CatalogTool, hace una llamada ZCatalog.searchResults con argumentos extra que limitan el resultado de lo que al usuario le está permitido ver.

El método searchResults() de ZCatalog acepta parámetros que definen una consulta a ser hecha al catálogo. La consulta puede ser pasada como una palabra clave (keyword), como un diccionario (mapping) o como parte de un objeto REQUEST, tipicamente desde un formulario HTML.

El índice del catálog a ser consultado será el nombre del keyword, una clave en un diccionario, o un atributo de un record object.

Atributos de los record objects

  • query: una secuencia de objetos o un único valor a ser pasado como consulta al índice (obligatorio).
  • operator: especifica la combinación de resultados de búsqueda cuando query es una secuencia de valores (opcional, por defecto: or). Valores permitidos: and, or, para Keyword Indexes y Path Indexes; and, or, andnot, near, para Text Indexes.
  • range: define un rango de búsqueda sobre un índice (opcional, por defecto: no activado). Valores permitidos: min, para buscar los objetos con valores más grandes que el mínimo de los valores pasados en el parámetro query; max, para buscar los objetos con valores más pequeños que el máximo de los valores pasados en el parámetro query; minmax, para buscar los objetos con valores más grandes que el mínimo de los valores pasados en el parámetro query y con valores más pequeños que el máximo de los valores pasados en el parámetro query.
  • level: se aplica sólo al índice Path. Especifica el nivel de directorio para comenzar la búsqueda (opcional, por defecto: 0)

Ejemplo 7: listar todos los documentos del portal inversamente ordenados por id.

El siguiente script lista todos los documentos del portal inversamente ordenados por id, notar que portal_type restringe el tipo de los objetos de contenido, y sort_on y sort_order hacen la ordenación propuesta. Si se quisiera ordenar por título, en Plone 2.1.1, deberíamos pasar el valor sortable_title en el parámetro sort_on:

* En un script python anda como está.
* En Clouseau (cambiando sutilmente la forma de mostrar los resultados):
>>> results = portal.portal_catalog.searchResults(sort_on='id', portal_type='Document', sort_order='reverse')
>>> [i.getPath().id for i in results]

Notar que usamos el método getObject puesto que el resultado arrojado por searchResults no son los objetos de contenido en sí. Es decir, el método get object devuelve el objeto de contenido asociado a un item del resultado de una búsqueda en el catálogo.

Ejemplo 8: listar todos los objetos del portal que sean privados y que incluyan la palabra texto.

Cada objeto de contenido define cuál de su información es searchable. El parámetro SearchableText busca sobre esa información en cada objeto. El parámetro review_state filtra objetos de acuerdo a su estado:

* En un script python anda como está.
* En Clouseau es similar al de arriba.

Ejemplo 9: listar todos los objetos del sitio cuya fecha de creación sea posterior al 30 de noviembre de 2005 y hayan sido creados por el usuario admin.

En este script se muestra cómo se puede pasar un record object al método searchResults. Al parámetro Date se le pasa un record object para consultar por aquellos objetos que fueron creados en una fecha posterior al 30 de noviembre de 2005. El parámetro Creator filtra aquellos objetos que no fueron creados por el usuario admin:
* En un script python anda como está.
* En Clouseau es similar al de arriba pero puede haber algún problema con el módulo DataTime.

Manipular usuarios y grupos

Describimos cómo usar la API de Plone para crear usuario, grupos y cómo asignar un usuario a un grupo.

Ejemplo 10:

* Crear la siguiente estructura jerárquica de objetos desde la interfaz Plone:
portal
folder1
doc1
folder2
* Desde Clouseau:
>>> folder2 = portal.folder1.folder2
>>> doc1 = folder2.doc1
>>> doc1.Title()
'Doc1'
>>> '/'.join(doc1.getPhysicalPath())
'/api/folder1/doc1'

Notar que folder2 no tiene ningún objeto con id doc1 dentro y que la expresión folder2.doc1 resolvió al objeto doc1 dentro de folder1.
La adquisición no sólo funciona para contención, sino también para atributos:

>>> doc1.default_page
'front-page'

En ese caso se está pidiendo el atributo 'default_page' a doc1. doc1 no tiene ese atributo, por lo tanto es adquirido de folder1, que tampoco lo tiene, y finalmente es adquirido del objeto portal, que tiene el valor 'front-page' en el atributo default_page. El atributo default_page tiene sentido en objetos que pueden contener otros objetos y define una vista predeterminada para el objeto contenedor. Si definimos doc1 como vista predeterminada para folder1, entonces el valor de la expresión doc1.default_page será 'doc1', pues la adquisición se detendrá en folder1.

Copyright (C) 2004-2007 Menttes - All Rights Reserved