19. Comportamientos

Usted puede extender la funcionalidad de su objeto Dexterity solo creando un adaptador que se adapte a su objeto Dexterity para agregar otra característica o aspecto.

Pero si usted desea utilizar este adaptador, debe saber saber de alguna manera que un objeto implementa este. Además, usted no puede fácilmente agregar más campos a un objeto con ese enfoque.

Enfoque Dexterity

Dexterity tiene una solución para ello, con adaptadores especiales los cuales se llaman y registran por el nombre del comportamiento.

Un comportamiento puede ser agregado a cualquier tipo de contenido a través de la Web y durante el tiempo de ejecución.

Todas las vistas predeterminadas deben conocer el concepto de comportamientos y cuando renderizar los formularios, las vistas también comprueban si hay comportamientos referenciados con el contexto actual y si estos comportamientos tienen un esquema propio, esos campos se mostraran adicionalmente.

Nombres y Teoría

El nombre del comportamiento no es un término estándar en el desarrollo de software. Pero es una buena idea pensar en un comportamiento como un aspecto. Usted está agregando un aspecto a tu tipo de contenido y usted quiere escribir su aspecto de tal manera, que funciona independientemente del tipo de contenido en el que se aplica el aspecto. Usted no debe tener dependencias a campos específicos de su objeto o de otros comportamientos.

Como un objeto le permite aplicar el principio Abierto/cerrado a los objetos de Dexterity.

Ejemplo práctico

Así que, vamos a escribir nuestro propio pequeño comportamiento.

En el futuro, queremos que nuestra presentación este representada también en Lanyrd (un Directorio Conferencia Social - Lanyrd.com). Por ahora nos limitaremos a ofrecer un enlace para que los visitantes puedan colaborar fácilmente con el sitio Lanyrd.

Así que por ahora, nuestro comportamiento sólo añade un nuevo campo para almacenar la dirección URL del servicio Lanyrd.

Queremos mantener una estructura limpia, así que creamos primero un directorio llamado behaviors, y luego lo incluimos dentro de las declaraciones ZCML de nuestro archivo configure.zcml.

<include package=".behaviors" />

Entonces, agregamos un archivo vació behaviors/__init__.py y un archivo behaviors/configure.zcml conteniendo el siguiente código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:plone="http://namespaces.plone.org/plone"
    i18n_domain="ploneconf.site">

  <plone:behavior
      title="Social Behavior"
      description="Adds a link to lanyrd"
      provides=".social.ISocial"
      />

</configure>

Y un archivo behaviors/social.py conteniendo el siguiente código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from plone.supermodel import model, directives
from plone.autoform.interfaces import IFormFieldProvider
from zope import schema
from zope.interface import alsoProvides


class ISocial(model.Schema):

    directives.fieldset(
        'social',
        label=u'Social',
        fields=('lanyrd',),
    )

    lanyrd = schema.URI(
        title=u"Lanyrd-link",
        description=u"Add URL",
        required=False,
    )

alsoProvides(ISocial, IFormFieldProvider)

Vamos a llevarlo a través de este paso a paso.

  1. Registramos un comportamiento en el archivo behaviors/configure.zcml. Nosotros decimos para qué tipo de contenido este comportamiento es válido. Para hacer esto, a través de la Web o en el perfil GenericSetup.

  2. Creamos una interfaz marker en behaviors/social.py para nuestro comportamiento y hacerlo también un esquema el cual contiene los campos que queremos declarar. Podríamos simplemente utilizar definiciones de campos de esquema en una clase zope.interface, pero utilizaremos un formulario extendido desde el paquete plone.supermodel, de lo contrario nosotros podríamos no usar las características del conjunto de campos.

  3. También añadimos un fieldset para que nuestros campos no se mezclen con los campos normales del objeto.

  4. Añadimos un campo de esquema URI normal para almacenar la dirección URI del servicio Lanyrd.

  5. Nosotros marcamos nuestro esquema como una clase que también implementa la interfaz IFormFieldProvider. Se trata de una interfaz marker, nosotros no necesitamos implementar nada para proporcionar la interfaz.

Agregándolo a nuestra Talk

Podríamos añadir este comportamiento ahora a través del panel de control de Plone llamado Tipos de contenidos Dexterity. Pero en cambio, lo haremos directamente de forma apropiada en nuestro perfil GenericSetup

Debemos agregar el comportamiento al archivo profiles/default/types/talk.xml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?xml version="1.0"?>
<object name="talk" meta_type="Dexterity FTI" i18n:domain="plone"
   xmlns:i18n="http://xml.zope.org/namespaces/i18n">
   ...
 <property name="behaviors">
  <element value="plone.app.dexterity.behaviors.metadata.IDublinCore"/>
  <element value="plone.app.content.interfaces.INameFromTitle"/>
  <element value="ploneconf.site.behaviors.social.ISocial"/>
 </property>
 ...
</object>