Personal tools
You are here: Home Aiuti ed Info Manuale di Plone 2 13. Sviluppare con Archetypes
To change the maximal image width select one of the following:

13. Sviluppare con Archetypes

Document Actions

contributors: creators: lallo effectiveDate: None expirationDate: None language: it rights: creation_date: 2005/02/08 12:54:50.001 GMT+1 modification_date: 2005/02/09 18:37:30.231 GMT+1 Content-Type: text/x-rst

Capitolo 13: Sviluppare con Archetypes

Archetypes è un ambiente di lavoro per automatizzare lo sviluppo di prodotti Plone. Una volta scritta una descrizione per un tipo di contenuto in Python, Archetypes gestisce quasi tutto il resto, incluso la creazione di viste e la modifica di moduli per lo sviluppatore. Questo permette di sviluppare rapidamente tipi di contenuto con una minima quantità di codice. E meno codice scritto significa minore probabilità di errori, meno codice da mantenere ai cambiamenti di Plone, un ciclo di sviluppo rapido, e generalmente costi più bassi.

Poiché l’intero prodotto è basato su questa descrizione di oggetto, permette di utilizzare tools per generare questo prodotto. Per esempio, ArchGenXML che tratteremo in un secondo tempo, permette di generare un prodotto in un tool Unifield Modeling Language (UML). Si può poi prendere il risultato del modello UML e passarlo ad ArchGenXML per avere immediatamente un prodotto da pubblicare in Plone; Non dovete davvero scrivere nessuna riga di codice. Se avete trovato quello script, il prodotto in Python del capitolo 12, che fosse un piccolo piacevole ma troppo duro lavoro, allora questo capitolo sara qualche cosa da apprezzare.

Questo non significa che Archetypes è giusto per ogni prodotto; qualche volta abbiamo trovato Archetypes essere un po’ troppo piccolo. Per esempio, in un caso il nostro tipo di contenuto aveva un campo, ove erano presenti circa 16 diverse permutazioni sui dati di quel campo, che voleva dire poco della struttura esistente di Archetypes usata. Quell'era un caso estremo, comunque. La maggior parte del tempo troverete che Archetypes è precisamente ciò di cui avete bisogno.

Molte persone si lagnano del fatto che Archetypes renda la vita un poco troppo facile agli sviluppatori, e chiaramente è difficile addebitare molto alle persone per un lavoro che può richiedere dieci minuti. Personalmente non abbiamo mai avuto un problema per questo, ed Archetypes ci ha tirato fuori da molte situazioni incresciose allorquando all'improvviso le specifiche sono cambiate da quattro tipi di contenuto a quattordici.

Abbiamo sentito un aneddoto riguardante una società di sviluppo di siti web. Quando la società visita dei clienti, si porta dietro un programmatore. Quando il client descrive le proprie necessità, il programmatore digita furiosamente attraverso Archetypes. Prima che la riunione sia finita, possono dimostrare un rapido prototipo del prodotto di lavora al client.

In generale, la maggior parte del team di sviluppo Plone ha adottato Archetypes come via per sviluppare prodotti, così ha molta parte di mente e realmente è divenuto lo standard per lo sviluppo di Plone. Alcune delle altre caratteristiche fondamentali di Archetypes sono le seguenti:

  • Crea automaticamente le pagine di vista e di modifica, così che non dovete davvero scrivere alcun codice nella modello di pagina.
  • Mantiene un unico Id oggetto. Ogni oggetto creato ha un Id unico che gli utenti non possono cambiare. Questo vuol dire che potete trovare un oggetto sempre, anche se è stato mosso.
  • Crea riferimenti tra gli oggetti. Ogni oggetto può avere qualsiasi numero di relazioni con alcuni altri oggetti. Per esempio, può avere qualsiasi numero di oggetti collegamento attaccati ad un item di notizie.
  • Possiede un’installazione di sicurezza standard. Tutto il lavoro di sicurezza è fatto per voi, così se volete l'installazione default, non deve cambiare nessuna cosa.
  • Ha svariate opzioni di memorizzazione, come conservare i vostri dati in un database relazionale invece che nel database standard di Zope.
  • Ha capacità di trasformazione dei dati, come cambiare, per esempio, Microsoft Word in Hypertext Markup Language (HTML).

Archetypes non è specifico per Plone ma può essere usato anche con altri framework (strutture) di Zope come Content Management Framework(CMF); al momento comunque è usato soprattutto da Plone. Eventualmente, quando Plone migrerà a Zope 3, è progettato che gli schemi di Archetypes e di Zope convergeranno. Usare quindi Archetypes è un buon modo di rendere … (impermeabile al futuro) il vostro prodotto così che sia compatibile con le future versioni di Plone.

In questo capitolo, tratteremo la costruzione di nuovi tipi di contenuto con Archetypes. In questo capitolo realmente collaboreranno insieme tutte le informazioni che avete imparato piuttosto rapidamente negli ultimi capitoli e corre attraverso dei concetti di base. Dopo avere dimostrato come installare Archetypes, prenderemo attraverso come creare un tipo di contenuto di base.

Introduzione a Archetypes

Archetypes viene fornito con l’installer e con pacchetti per Plone, così che avete delle opportunità che abbiate già installato Archetypes nella vostra distribuzione. Se non siete sicuri che questo sia il caso, dovreste essere capace di vedere Archetypes nei parte Products del pannello di controllo di ZMI. In questo esempo, abbiamo esaminato Plone con Archetypes versione 1.2.5-rc4. Se avete installato Archetypes, saltate alla sezione "Sviluppare con Archetypes".

Per installare Archetypes, avrete bisogno di andare nel sito web presso http://sf.net/projects/archetypes, cliccate File e troverete l'ultima distribuzione di Archetypes. Nel nostro esempio, questo è, archetypes-1.2.5-rc4.tgz. Avrete bisogno di unzip esso, come così:

$ tar -zxf archetypes-1.2.5-rc4.tgz
$ cd archetypes-1.2.5-rc4l

A questo punto avrete bisogno di decidere cosa installare. Il minimo da installare è la directory Archetypes ed il generatore e moduli di validazione. Per installare questi moduli, muoveteli all’interno della directory Products della vostra instanza home. Di nuovo, nel nostro caso questo è / var/zope, così che il comando è il seguente:

$ mv Archetypes /var/zope/Products
$ mv generator /var/zope/Products
$ mv validation /var/zope/Products

ArchExample ed ArchGenXML sono entrambi opzionale, e non avete bisogno di loro per lavorare in Plone; comunque, li trattiamo entrambi come esempi in questo capitolo, così vorrete probabilmente installarli.

Per installare ArchExample, muovete il prodotto ArchExample all’interno della directory Products della vostra instanza home, come così:

$ cd ..
$ mv ArchExample /var/zope/Products

Se volete usare ArchGenXML, non avete bisogno di installarlo in un luogo particolare, così lo potete porre in qualsiasi directory ove non lo dimenticherete. Solitamente lo posizioniamo assieme nella directory Products della nostra istanza home. Non fa danno, e non lo dimentichiamo. Per esempio:

$ mv ArchGenXML /var/zope/Products

Come affermato nella documentazione di ArchGenXML, ArchGenXML richiede l’installazione PyXML. Di nuovo, se usate un installer Windows od un installer Mac, questo viene già incluso. Se non, allora andate presso http://pyxml.sf.net e scaricate il pacchetto. Nel nostro caso, l'ultimo pacchetto disponibile era 0.8.3, così dopo averlo scaricato, eseguimo il seguente:

$ tar -xvf PyXML-0.8.3.tar.gz
$ cd PyXML-0.8.3
$ python setup.py install

Nota

Solitamente, l’installazione eseguita in questo modo richiede su Unix i diritti di root per installare nella cartella Python.

Ora che avete settato tutto ed installò, vedremo alcuni esempi.

Tuffarsi in Archetypes

Un intero gruppo di grandi esempi è disponibile per Archetypes, così piuttosto che costruirne uno per il libro, mostriamo ArchExample, che viene fornito con l'installazione di Archetypes. Questo aggiunge un tipo di contenuto chiamato article che fornisce un esempio grezzo della potenza di Archetypes.

Article.py contiene il codice del prodotto principale. Vedete che il codice sembra piuttosto diverso dagli esempi precedenti. Contiene schema

StringField("blurb",
            searchable = 1,
            widget = TextAreaWidget(),
            ),

Questo pezzo di codice denota che avete un attributo sul tipo di contenuto chiamato fascetta (blurb), che è una stringa, e verrà mostrata come una text area HTML. Discuto tutte le opzioni per campi e widgets in un momento. Per ora, diamo un sguardo al tipo di contenuto Plone. In figura 13-1, abbiamo aggiunto tipo di contenuto blurb.

../pb2_en/img/3294f1301.png

Figura 13-1. La parte di blurb del tipo di contenuto

Con solo queste quattro linee di codice, avete aggiunto un campo al vostro tipo di contenuto. Gli elementi del modulo standard che si aspetterebbe Plone sono presenti; se modificate qualche cosa e ritornate in un secondo tempo, il vecchio valore è mostrato, gli errori sono tattati con eleganza, e così via. Come dimostrazione di come sia facile modificare, cambiate l'etichetta nel modulo per visualizzarlo come Article Blurb, e cambiate il campo per essere richiesto. Per fare questo, fate le seguenti modifiche:

StringField("blurb",
            required = 1,
            searchable = 1,
            widget = TextAreaWidget(label="Article Blurb"
            ),

Qui avete aggiunto il parametro required = 1 che rende questo campo obbligatorio, ed un parametro all’etichetta. Se riavviate Plone ed aggiunge un nuovo article, l'interfaccia utente è ora cambiata per riflettere il nuovo schema. Il campo è ora chiamato Artiche Blurb.

../pb2_en/img/3294f1302.png

Figura 13-2. La parte del tipo di contenuto di Article Blurb

Questo non è solamente un cambio estetico; il cambio riflette la modifica dello schema fondamentale, e questa è la vera potenza di Archetypes. Solamente comparando questo con lo scrivere prodotti in Python, potete vedere che tutto il lavoro faticoso dallo scrivere un prodotto è stato rimosso. È come questo: se si può definire un schema, poter mettere insieme completamente un archetipo è assolutamente immediato. Una volta che avete fatto, potete modificarlo facilmente e potete vedere le modifiche prendere effetto.

Se fate qualsiasi di queste modifiche per provare gli esempi seguenti, dovrete riavviare Plone. Solamente allora tutti i nuovi cambiamenti saranno caricati e propriamente registrate. Per ulteriori informazioni su questo, vedete successivamente la sezione "Sviluppare con Archetypes" in questo capitolo.

Spiegare Schema, Campi e Widgets

La definizione fornita dal dizionario di Merriam-Webster di schema è la seguente:

schema:

Nel linguaggio Archetypes, un schema

<manca qualcosa - Ugo >

Ogni campo ha un widget definito. Un widget

Figura 13-3 Mostra la relazione tra schema, campi, e widgets.

../pb2_en/img/3294f1303scrap.png

Figura 13-3. La relazione tra schema, campi, e widgets

Schema ed il BaseSchema

Per creare un schema, passate i campi che desiderate nell'oggetto schema come un tuple di campi. Per esempio, lo schema dell'article ha tre campi: group, blurb, e body. Il seguente codice avvia lo schema:

Schema((
    StringField('group',
        vocabulary=ARTICLE_GROUPS,
        widget=SelectionWidget(),
        ),
        # other fields here
        )

È possibile aggiungere schema per trovare una sommatoria di più di uno schema. Questo è precisamente quello che fa davvero ArchExample: aggiunge gli schemi definiti nel tipo di contenuto ad un schema chiamati BaseSchema.

Il BaseSchema contiene due elementi che ogni tipo di contenuto di Plone dovrebbe avere, un titolo (title) ed un Id. Il titolo è richiesto così che qualche cosa possa essere visualizzata nell'interfaccia utente, e lo Id, o in breve nome, corrispondete alle convenzioni standard di Plone per un schema chiamante. I due schema sono aggiunti semplicemente per creare un schema più grande. In ArchExample, per fa questo aggiungete lo schema per il tipo di contenuto al BaseSchema già esistente. Per esempio:

schema = BaseSchema +  Schema((
    StringField('group',
                vocabulary=ARTICLE_GROUPS,
                widget=SelectionWidget(),
                ),
    ...

E’ chiaro che gli items sono restituiti dalla query dello schema nell'ordine con cui sono aggiunti allo schema. Questo vuol dire che potete riordinare l'ordine degli elementi che appaiono nell'interfaccia utente solamente muovendo i campi all’interno dello schema. Ecco anche perché il BaseSchema è aggiunto all'inizio così che lo Id ed il campo titolo appariranno in cima alla vista e della pagina di modifica, piuttosto che al fondo.

Campi

Quindi avete visto che il campo StringField è un campo comune che rappresenta una stringa nel vostro tipo di contenuto. Un numero di campi è disponibile in Archetypes, come descritto in tabella 13-1. Con il tempo, più campi sono aggiunti, e se avete bisogno, è possibile creare il vostro proprio.

Ogni campo ha un widget di default che verrà usato, a meno che ne specificate uno. Nell'esempio precedente blurb, specificamo un TextAreaWidget. (Widget sono trattati nella prossima sezione.) Tutti questi campi sono importati dal modulo pubblico di Archetypes; per esempio:

from Products.Archetypes.public import BooleanField

Tutti i campi sono instanziati allo stesso modo – creando un campo e passando nell’unico parametro richiesto per il campo: name. Potete passare opzionalmente qualsiasi numeri di parametri fondamentali secondo necessità. Per esempio:

from Products.Archetypes.public import IntegerField
# a simple field for age
age = IntegerField('age')
Tabella 13-1. I campi ottenibili in Archetypes
Nome Tipo Default Widget Descrizione
BooleanField Boolean values ComputedWidget Simple storage of true or false for a field.
DateTimeField Date and time objects CalendarWidget For storing dates and times.
FileField Files FileWidget Storage for large chunks of data such as plain-text files, Microsoft Word documents, and so on.
FixedPointField Fixed-point numbers DecimalWidget For storing numerical data with fixed points.
FloatField Floats DecimalWidget For storing numerical data with floating points.
ImageField Image ImageWidget Stores an image and allows dynamic resizing of the image.
IntegerField Integer StringWidget For storing numerical data as integers.
LinesField Lists LinesWidget A list of data such as keywords.
PhotoField Image PhotoWidget Same as an image field but has more default image sizes.
ReferenceField Reference ReferenceWidget Contains a reference between this object and another.
StringField String StringWidget A string field optimized for smaller strings—say, fewer than 100 words.
TextField String TextWidget A string field optimized for larger strings—say, larger than 100 words. The string can also be transformed into multiple formats.

Ciascuno dei campi hanno attributi che possono essere assegnati al campo. Già ne avete visto almeno due: il name e l’attributo widget. L'attributo name è l'unico parametro richiesto ad un campo e dovrà essere unico, minuscolo, e senza spazi o punti. L'attributo name verrà usato solamente all’interno, conficcarsi cosi che questa regola chiamate sia importante. Tutti gli altri valori sono opzionali. Tabella 13-2 descrivono gli attributi.

Tabella 13-2. Gli attributi dei Campi
Nome Descrizione Possibile Valore
accessor The name of the method to get the value of the field, so you could change how this field is retrieved Any method name (for example, specialGetMethod) See the 'Overriding Default Methods” section later in this chapter.
default The default value for the field. Should be appropriate to the field.
default_method A string for obtaining a value for the field; one is created for you by default if you don't define one. Any string (for example, getSpecialDescription). See the 'Overriding Default Methods” section later in this chapter.
edit_accessor The name of a method to get the raw value of a field. Any method name (for example, rawGetMethod). See the 'Overriding Default Methods” section later in this chapter.
enforceVocabulary If enabled, you won't accept anything outside the vocabulary. True or False.
index If you want this field to be placed in its own catalog index, then specify the type of index here as a string. If you append :schema onto the end of the schema, then this will also be added as a metadata column. The name of any index, such as KeywordIndex or KeywordIndex:schema.
name A unique name for this field. Any string, lowercase conforming to standard Python variable rules (for example, description, user_name, or coffee_bag_6).
mode The read and write mode of field, as a string; the default is to be read and write. For read only: r, for write only: w, for read and write: rw.
multiValued If this field can have multiple values, this is useful for things such as drop-down lists. True or False.
mutator The name of the method to alter the value of the field, so you could change how this field is set. Any method name (for example, specialSetMethod). See 'Overriding Default Methods” later in this chapter.
primary If True on a field, then this will be the field that responds to File Transfer Protocol (FTP) and WebDAV requests. There can be only field that does this; if multiple are defined, the first one in the schema will be used. You normally do this for the main body attribute. True or False.
required Specifies that some value for this field required. True or False.
schemata Place the field into the grouping of other fields called schematas  
default    
metadata    
user_information    
searchable A boolean that specifies if this field will be added to the searchable text and can be used in the searches. True or False.
validators The validations that will be performed on the field as a tuple of strings; it starts at first and validates against each validation. Any validator; see the 'Validations of Input” section later.
vocabulary A list of values that a user can choose from, for example, the values to show in a drop-down list. List of strings (for example, ["Green", "Red", "Blue"]).
storage Where to store the value; the default is Attribute Storage, which stores the field as an attribute of the object. Any valid storage object such as AttributeStorage or SQLStorage. You can find these in the Archetypes Application Programming Interface (API). For more information, see the 'Storing Your Content in a SQL Database” section later in this database.
widget The widget that will be used to display this field. Any widget object.

Ora che abbiamo trattato i campi di default e gli attributi, è ora di muoversi sopra l’attuale widgets che sia disponibile.

Widgets

Un widget contiene le informazioni di come l'oggetto verrà rappresentato visivamente. La vista di un attributo visualizzato è spesso riferita da vicino al tipo dell'attributo; comunque, avete opzioni per visaulizzare – una stringa può essere selezionata in molti modi. Dato il set di widgets, l'oggetto widget può essere pressocché qualsiasi cosa. Potete importare qualsiasi widgets dal modulo * pubblico* di Archetypes. Per esempio:

from Products.Archetypes.public import BooleanWidget

Tutti i widgets sono instanziati allo stesso modo – creando un widget e passando in parametri fondamentali come necessita. Per esempio:

from Products.Archetypes.public import IntegerField
from Products.Archetypes.public import IntegerWidget
# a simple field for age
age = IntegerField('age',
       widget=IntegerWidget(label="Your age")
       )

Widgets può avere anche attributi extra, dipendendo dal tipo di widget. In molti casi, questi attributi addizionali corrispondono direttamente agli attributi HTML; per esempio, su un StringWidget potete mettere un attributo size. Questo produrrà l’adatto widget HTML con settato l’attributo size HTML. Cosi che per avere un input che sia grande 20 caratteri, dovete creare il seguente widget:

bankAccountNumber = StringField('bank',
   widget=StringWidget(
           label="Bank account number",
           size=20)
         )

La tabella 13-3 descrive di tutti i widgets disponibili in Archetypes.

Tabella 13-3. I Widgets disponibili
Nome Descrizione Altri Attributi
BooleanWidget Shows two checkboxes for the possible values.

System Message: INFO/1 (<string>, line 362)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

CalendarWidget Returns a set of input boxes with a link to a helper pop-up box so that a user can select a date.

System Message: INFO/1 (<string>, line 364)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

ComputedWidget Returns the computed value as HTML.

System Message: INFO/1 (<string>, line 366)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

DecimalWidget A simple HTML input box for a string. size.
EpozWidget An HTML Epoz widget that shows the Epoz rich-text editor for the content. You can provide format, rows, mode, and cols (for columns).
FileWidget Displays an HTML file element for users to upload files.

System Message: INFO/1 (<string>, line 372)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

IdWidget A simple HTML input box that's used for rendering autogenerated IDs.

System Message: INFO/1 (<string>, line 374)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

ImageWidget Shows and allows the editing of images. You can provide a display_threshold that allows you to set the size of an image; if it's below this size, the image will display in the Web page.
IntegerWidget A simple HTML input box for a string. size.
KeywordWidget This displays a list of keywords from the catalog in a complicated widget, such as the one in the Properties tab on a normal object.

System Message: INFO/1 (<string>, line 380)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

LabelWidgets Used to display labels on forms; no values or form elements.

System Message: INFO/1 (<string>, line 382)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

LinesWidget Displays a text area that users can enter values. rows and columns.
MultiSelectionWidget A selection widget; by default it's an HTML select widget. format, which can be one of select or checkbox.
PasswordWidget An HTML password element.

System Message: INFO/1 (<string>, line 388)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

RichWidget Allows the input of a file in multiple formats that are then transformed. See 'Transforming Data,” later in this chapter for more information. You can provide rows, cols *(columns), and *format.
ReferenceWidget Shows an HTML select element of a list of possible references.

System Message: INFO/1 (<string>, line 392)

Unexpected possible title overline or transition. Treating it as ordinary text because it's so short.

--

SelectionWidget Shows a selection widget. If it's flex (the default), then if the number of choices is more than four, a select element is used; otherwise a radio button is used. format, which can be one of flex, select, or radio.
StringWidget A simple HTML input box for a string size and maxlength.
TextAreaWidget A text area widget that allows the uploading of the content in multiple formats You can provide allowed_content_types, which is a list of string; each string represents a meta_type of the type of content uploaded.

Per ciascun widgets elencato in tabella 13-3, la tabella 13-4 descrive tutti gli attributi che sono comuni ad ogni widgets. Avete già visto l’attributo label che sette la descrizione sul vostro widget. In congiunzione con gli attributi extra per ciascun widget, avete un set completo di attributi dei widget.

Tabella 13-4. Valori possibili per i Widgets
Nome Descrizione Valori possibili
label The label that will appear in the user interface with this field. Any string, for example, Start Date for a field start_date.
modes The modes that this widget will be shown in; by default there are two modes: view and edit. A list of modes as strings; by default it's ("view", "edit").
populate If this is enabled, the view and edit fields will be populated. Usually this enabled, but for fields such as a password field, this shouldn't be the case. Usually this is true by default. True or False
postback If this is enabled, then when an error is raised, the field is repopulated; for fields such as a password field, this shouldn't be the case. Usually this is true by default. True or False
visible If the attribute should be visible in the user interface. This is a dictionary mapping the view mode to a string, describing the visibility. Choices are visible, hidden (shown in an HTML hidden form value), invisible (not shown at all). For example, {'view': 'visible', 'edit': 'hidden' } means that the view will show, but the edit page will hide the value.
Alcuni esempi di combinazione di campi e di widget

Questa sezione contiene alcune combinazioni utili che sembrano essere usate comunemente e che potete trovare utili come esempi. Per questo esempio, creiamo un casella a discesa della vostra frutta preferita. Definiremo l'attributo vocabulary come un lista di stringhe. Ognuno dei valori della lista è una stringa del tipo fruit; per cui, il tipo di campo è un StringField. Poiché stiamo definendo il widget come un SelectionWidget, si presenterà come un casella a discesa, così come:

StringField('fruit'
    vocabulary = ["Apple", "Orange", "Mano", "Banana"],
    widget = SelectionWidget(label = "Favourite Fruit")
    )

La ImageField è utile per creare e mantenere immagini in un sito Plone. Per avere un bel semplice campo dove gli utenti possono caricare [upload] immagini, usiamo il seguente:

ImageField('portrait',
    widget = ImageWidget(label = "My picture"),
    )

Il tipo seguente è un tipo veramente complicato di contenuto. La maggior parte dei contenuti digitati possiedono un campo principale che può ricevere dati. Se pensate al tipo di documento di base, osserverete un campo corpo (body) ove digitate e modificate. Questo unico campo body è il testo principale del tipo di contenuto. Quindi per questo campo standard, avete solamente alcuni attributi che dovranno essere aggiunti.

Per primo, desiderate che questo campo sia ricercabile, così dovete impostare l'attributo searchable. Successivamente, vorrete che questo campo risponda alle richieste FTP e WebDAV, così dovete impostare l'attributo primary (potete trovare ulteriori informazioni su questo nel sidebar "Il campo primary: Ordinare e Rispondere a FTP e WebDAV"). Desiderate che siano caricati [upload] molteplici tipi di contenuto, così, per questa ragione, settate * allowable_content_types*. Avete bisogno di sapere chiaramente, poi, come visualizzare il campo, così, per questo ponete * default_output_type*. Tutto questo allora fornisce il campo seguente:

TextField('body'
          searchable = 1,
          primary = 1,
          default_output_types = 'text/html',
          allowable_content_types = ('text/plain',
                                     'text/structured',
                                     'text/restructured',
                                     'text/html'),
          widget = RichWidget(label = 'Body'),
          )
Il campo primary: Ordinare (Marshaling) e Rispondere a FTP e WebDAV

Plone è un sistema orientato agli oggetti dove un oggetto possiede molti attributi e non può essere rappresentato semplicemente come un file in chiaro [plain]. Sfortunatamente, molti dei protocolli esistenti come FTP e WebDAV trattano contenuto precisamente in questo modo. Avete bisogno quindi là di qualche strada per tradurre fra i due, e il campo primary fa questo. Avendo settato il campo primary su un oggetto, questo campo diverrà l’unico che spedisce e riceve da questi protocolli – piuttosto che l'oggetto intero.

Questa è una soluzione imperfetta ad un problema ingannevole, chiaramente. Se avete usato FTP o External Editor su un file, saprete che tenta di risolvere questo posizionandoun numero di linee in cima alla pagina che contengono chiavi/valori per i metadata sull'oggetto. Questo è un altro tentativo di risolvere lo stesso problema.

Per impostare il campo primary marshaling, abbiamo bisogno di aggiungere il seguente al vostro schema: marshall=some_marshaller (). Ci sono attualmente, solamente due marshalers: un PrimaryFieldMarshaller che prende l’intero contenuto e lo posiziona all’interno del vostro oggetto ed un RFC822Marshaller. Questo secondo marshaler si occupa del contenuto per il campo name/value come usato nella posta elettronica. Per gli scopi di questo capitolo, useremo il PrimaryFieldMarshaller per occuparci del contenuto con External Editor.

Validare un Input

Sebbene i moduli si occupino del contenuto e degli errori di base, cosi come ommettere il contenuto, piuttosto bene, probabilmente vorrete avere una gestione degli errori più sofisticata. Potete fare una serie di validazioni per esaminare che il contenuto nel vostro tipo di contenuto sia corretto. Per esempio, se avete un campo numero intero, vorrete probabilmente controllare che i dati che sono stati aggiunti siano quello che si è voluto dire di essere.

Potete aggiungere un parametro di validazione al campo per fare ciò. Per controllare che il vostro IntegerField sia un numero intero, per esempio, in realtà farete questo:

from Products.Archetypes.public import IntegerField
from Products.Archetypes.public import IntegerWidget
# a simple field for age
age = IntegerField('age',
      validators=("isInt"),
      widget=IntegerWidget(label="Your age")
      )

Da dove viene isInt? Bene, isInt è il nome di un validatore registrato nella struttura di validazione. Solamente alcuni sono là, ma sono piuttosto utili; la tabella 13-5 li descrive. Per i dettagli esatti di ciascuno di essii, raccomandiamo di leggere il codice e guardare all'expressione regolare – potete trovarli nel modulo validation/validators/__init__.py della vostra directory Products:

Table 13-5. Validatori disponibili
Name Description
isDecimal This validates that the string is a decimal, including positive and negative, exponentials, and so on.
isInt This validates that it's an integer.
isPrintable This validates that this is a letter or a number.
isSSN This validates that it's nine numbers (the length of a U.S. Social Security number).
isUSPhoneNumber This validates that it's ten numbers and is optional.
isInternationalPhoneNumber This validates that it's at least one number and is optional.
isZipCode This validates that it's five or nine numbers.
isURL This validates that the input starts with http://, ftp://, or https://.
isEmail This validates that this conforms to the standard e-mail syntax.

Potete registrare anche le vostre proprie validazioni. Un Validatore di fatto è una semplice classe che implementa l'interfaccia ivalidator. Due sono sempre fatte: un RegexValidator che verifica un'espressione regolare ed un RangeValidator che verifica una serie di valori. Per registrare un nuovo validatore che controlli che un utente abbia un’età compresa fra 0 e 150 anni (sembra ragionevole), aggiungerete ciò che segue al vostro tipo di contenuto nel modulo Python, prima di creare il campo:

from validation.validators.validator import RangeValidator
from validation import validation
 
# the RangeValidator takes a name for the validator
# and a start and end value
validAge = RangeValidator("validAge", 0, 150)
validation.register(validAge)

Poi potete cambiare il vostro validatore al seguente:

validators=("isInt","validAge"),

Per primo, il codice verificherà che abbiate un numero intero valido; successivamente, controllerà che il numero intero sia all'interno dell’intervallo di età ragionevole. Se volete aggiungere un Validatore totalmente nuovo che esegua qualche cosa di diverso di un'espressione regolare o della validazione di serie, avrete bisogno di aggiungere un nuovo sistema di validazione. Per questo esempio, create una validazione che una data sia compresa fra due valori. Nell'esempio seguente, questo è chiamato DateRangeValidator e restituirà un valore di booleano se la data fornita è compresa tra due date date. Questo potrete essere utile per affermare che una vacanza sia all'interno delle vacanze scolastiche.

Quindi, ora definite un nuovo validatore chiamato DateRangeValidator nel modulo validators. Questo permette di registrare lìintervallo delle date per affermare che la data richiesta cada nel mezzo. Userete, per fare ciò, l’oggetto Zope DateTime (che verrà trattato più in dettaglio Nell’Appendice A). Un validatore è semplicemente - è una classe che ha un nome e che risponde al metodo __call__ * di controllo della data. Ciò che segue è la classe *DateRangeValidator , che è stata aggiunta al modulo validator:

from DateTime import DateTime
 
class DateRangeValidator:
    __implements__ = (ivalidator,)
 
    def __init__(self, name):
        self.name = name
 
    def __call__(self, value, *args, **kwargs):
        min, max = args[:2]
        if not isinstance(value, DateTime):
            value = DateTime(value)
 
    return min < value and value < max

Dopo riavviate Zope, ora potete registrare una nuova validazione, come:

from validation.validators.validator import DateRangeValidator
from validation import validation
from DateTime import DateTime
 
christmas = DateRangeValidator("ChristmasHolidays",
    DateTime('12/18/2004'),
    DateTime('01/09/2005'),)
validation.register(christmas)

Infine potete creare un validazione nel vostro schema nella seguente maniera:

validators=("christmas",)
Sovrascrivere [Overrindig] Viste ed Actions nella classe Base

Archetypes crea viste predefinite ed azioni basate su un set standard di requisiti che vanno bene per molte necessità. Le azioni sono vedere, modificare, e le proprietà, chiaramente; i riferimenti sono un'altra azione che guarderà a lui un momento. Non trovete i modelli di pagina dell’oggetto per vista od edita; questi sono generati automaticamente da Archetypes. Comunque, potete modificarli.

Ci aspettiamo che in molti casi vorrete avere la priorità sul metodo vista e di offrirne uno proprio vostro; Di default è base e non è mirata all’inizio una pagina perfetta (chiaramente, essendo una pagina Plone, è migliore del vostro sistema di gestione dei contenuti medio). Comunque, potete avere specifiche necessità che fanno riferimento al contenuto; forse è una questione di presentare il vostro contenuto in un certo modo.

Archetypes di fatto crea una classe per ogni tipo di contenuto. Molto nello stesso modo in cui avete creato una classe per il tipo di codice sorgente nel capitolo precedente, potete creare una classe base per il vostro archetipo. Questa classe base è stata chiamata BaseContent ed è disponibile nel modulo public di Archetypes per l’importazione. Questa classe BaseContent definisce ogni cosa di cui Archetypes ha bisogno di conoscere. Realizzando questa classe vi viene offerta un'opportunità di avere la priorità pressocché su qualsiasi cosa che desiderate nella classe.

Come ora mostriamo, ci sono due parti per questo. Prima, create un'azione che verrà usata dalle informazioni di tipo di fabbrica [factory]; in Archetypes fate questo assegnando l’attributo action della classe. Per esempio:

from Products.Archetypes.public import BaseContent
 
class Article(BaseContent):
    # other stuff
    actions = ({ 'id': 'view',
                 'name': 'View',
                 'action': 'string:${object_url}/article_view',
                 'permissions': (CMFCorePermissions.View,)
                },)

Secondo, avete bisogno di creare un modello di pagina, chiamato article_view, per la vista attuale dell'oggetto. Questa stringa definisce un modello di pagina che il tipo di contenuto localizzerà nello skin per questo prodotto. In questo caso, troverà il modello di pagina corrispondente nel File System nella directory dello skin/archexample di ArchExample. Potete trovare anche una copia di questo modello di pagina nell’Appendice B. Questo può essere un semplice o un complicato un modello di pagina come desiderate.

Per prendere efficacia, dovete ravviave Plone per le modifiche. In questo caso, state modificando un'azione installata all’interno del tool portal_types allorquando il prodotto è stato installata. Per questa ragione, se cambiamente questa azione, avrete bisogno di reinstallare il prodotto. Per fare questo nell'interfaccia Plone, cliccate Plone setup.

Tutti gli elementi nel tipo d’informazione di factory possono essere soprascritte [overriden] creando un attributo di quel nome sull'oggetto. Per sovrascrivere content_icon create un attributo chiamato content_item. Per esempio:

class SomeProduct(BaseContent):
          """ Some product """
          content_icon = "some_icon.gif"
Sovrascrivere i metodi di Default

Nella Tabella 13-2, abbiamo menzionato la possibilità di sovrascrivere alcuni metodi di default che occorrono sui tipi di contenuto, come accessor e mutator. Questa è un opzione avanzata che permette la manipolazione dei campi al momento della modifica (da rivedere).

Giusto come il progetto open source dell'ultimo capitolo, potete accedere a questi attributi od a questi campi usando i mediti accessors e mutator. Alcuni metodi default sono disponibili. Se il vostro nome del campo è blurb, allora questi metodi saranno getBlurb e setBlurb. Il termine get <manca qualcosa – Ugo >

Comunque, potete volere fare qualche cosa di diverso in accessor o mutator. Supponete di voller filtrare il valore di un campo, come correggere sempre l’ortografia del nome della vostra società o cambiare il valore di alcune altri campi quando un certo compo viene modifica. Allora potete fare così avendo la possibilità di sovrascrivere i metodi predefiniti. Nell'esempio seguente, realizzerete un nuovo metodo chiamato getSpecialBlurb che prende il blurb che qualcuno ha digitato e lo manipolerete prima di ritornarlo al client. In questo caso, state sostituendo il testo Perl

getSpecialBlurb Article

class Article(BaseContent):
 
    def getSpecialBlurb(self):
        """ The view for an article """
        blurb = self.getField('blurb').get(self)
        blurb = blurb.replace('Perl', 'Python')
        return blurb

Avrete bisogno di modificare anche il vostro campo così che usi questo metodo:

StringField('blurb',
    searchable=1,
    widget=TextAreaWidget(),
    accessor="getSpecialBlurb",
),

In questo esempio, in qualsiasi momento che il campo blurb ha accesso, per esempio, ad una pagina di vista o di modifica viene restituito il valore di getSpecialBlurb. Archetypes conosce l’accesso al metodo poiché il nome del metodo è definito come un valore stringa passato al parametro accessor. C'è un bit di frode voluta – per accedere al valore crudo dell'attributo, avete bisogno di trovare il campo e poi invocare il metodo get. Questo è una linea piuttosto confusa blurb=self.getField ('blurb'). get(self). Il pattern getting il campo e quindi (ri)chiamare un metodo su lui è davvero piuttosto comune in Archetypes [da rivedere… ndt].

L'esito pratico di questo ora è che, non vi è nessuna questione quando o come una persona digiti la parola Perl

Mettere insieme il resto del tipo di contenuto

Ora abbiamo trattato tutti gli elementi principali del tipo di contenuto. Il listato 13-1 mostra tutto insieme il codice. Noterete che il resto del codice è più compatto del prodotto Python perché Archetypes lavora così molto per voi.

Listato 13-1. Article.py
from Products.ArchExample.config import ARTICLE_GROUPS
from Products.Archetypes.public import BaseSchema, Schema
from Products.Archetypes.public import StringField, TextField
from Products.Archetypes.public import SelectionWidget, TextAreaWidget
from Products.Archetypes.public import RichWidget
from Products.Archetypes.public import BaseContent, registerType
from Products.Archetypes.Marshall import PrimaryFieldMarshaller
from Products.CMFCore import CMFCorePermissions
from config import PROJECTNAME
 
schema = BaseSchema +  Schema((
    StringField('group',
                vocabulary=ARTICLE_GROUPS,
                widget=SelectionWidget(),
                ),
    StringField('blurb',
                searchable=1,
                widget=TextAreaWidget(),
                ),
    TextField('body',
              searchable=1,
              required=1,
              primary=1,
              default_output_type='text/html',
              allowable_content_types=('text/plain',
                                       'text/structured',
                                       'text/restructured',
                                       'text/html',
                                       'application/msword'),
              widget=RichWidget(label='Body'),
              ),
           ),
     marshall=PrimaryFieldMarshaller(),
     )
 
class Article(BaseContent):
    """This is a sample article; it has an overridden view for show,
    but this is purely optional
    """
 
    schema = schema
 
    actions = ({
        'id': 'view',
        'name': 'View',
        'action': 'string:${object_url}/article_view',
        'permissions': (CMFCorePermissions.View,)
        },)
 
registerType(Article, PROJECTNAME)

A parte un gruppo di importazioni in alto e lo schema, abbiamo trattato tutti i contenuti di questo codice, con un'eccezione: registerType. Questa funzione registra il vostro oggetto con il prodotto. Ciascun prodotto può avere moltiplici tipi di contenuto, così questa funzione prende l'oggetto ed il nome del progetto. In questo caso, il nome del progetto è importato dal file di configurazione, come visto precedentemente. Il file di configurazione, config.py contiene variabili similari per la configurazione del prodotto, come mostrato nel listato 13-2.

Listato 13-2. Il file di configurazione di ArchExample
from Products.CMFCore.CMFCorePermissions import AddPortalContent
from Products.Archetypes.public import DisplayList
 
ADD_CONTENT_PERMISSION = AddPortalContent
PROJECTNAME = "ArchExample"
SKINS_DIR = 'skins'
 
GLOBALS = globals()
 
ARTICLE_GROUPS = DisplayList((
    ('headline', 'Headline'),
    ('bulletin', 'Special Bulletin'),
    ('column', 'Weekly Column'),
    ('editorial', 'Editorial'),
    ('release', 'Press Release'),
    ))

La variabile ARTICLE_GROUPS è un tuple di un tuple di stringhe per usarla nel group widget. Potrete usare solo una semplice tuple di stringhe, ma in questo caso l'esempio sta usando la classe DisplayList che è un'occassione di mostrare un diverso valore all'utente da quello che sarà messo nel modulo. In questo caso, lo HTML per ArticleGroups è visualizzato in un elemento HTML scelto, come così:

<option value="headline">Headline</option>
<option value="bulletin">Special Bulletin</option>
...

Un altra intuizione insolita è l'uso della funzione globals - che è una funzione nativa [built-in] di Python, che contiene tutti i simboli globali. Questo calcola il path della directory dello skin nel File System così che possiate costruire una vista delle directory del File System dello skin per il tool skin. La funzione di inizializzazione del prodotto, __init__.py è anche molto più semplice. Con una nuova inclusione, il processo e la lista delle funzioni tipo sembrano questi:

from Products.Archetypes.public import process_types, listTypes
content_types, constructors, ftis = process_types(
    listTypes(PROJECTNAME),
    PROJECTNAME)

La funzione listTypes è un'utilità di Archetypes che restituirà tutti i tipi che prima avete registrato. Questi quindi verranno passati alla funzione process_types che a turno ritorna tutti i tipi di contenuto, i costruttori, e gli oggetti tipo factory information. Questi sono tutti gli stessi items che avete registrato nel prodotto Python; è solo che questa funzione di utilità rende tutto un pò più facile.

Finalmente, avete la funzione di installazione nel Extensions install.py. Questo script è ora imbarazzantemente piccolo perché di tutto il lavoro che avete fatto prima si sono occupati due funzioni di utilità, installTypes ed install_subskin. Il termine subskin <manca qualcosa – Ugo >

Listato 13-3. Script d'installazione
from Products.Archetypes.public import listTypes
from Products.Archetypes.Extensions.utils import installTypes,
install_subskin
from Products.ArchExample.config import  PROJECTNAME, GLOBALS
 
from StringIO import StringIO
 
def install(self):
    out = StringIO()
    installTypes(self, out, listTypes(PROJECTNAME), PROJECTNAME)
    install_subskin(self, out, GLOBALS)
    out.write("Successfully installed %s." % PROJECTNAME)
    return out.getvalue()

La versione completa di ArchExample è disponibile nel sito web del Plone Book presso http://Plone-book.agmweb.ca, e dovreste essere capace di lasciar cadere questo e di eseguirlo sul vostro sito. Come avete visto, questo tipo di contenuto è rapido e facile da sviluppare ed è facile da modificare, senza dovere scrivere molto codice.

Sviluppare con Archetypes

Questa sezione fornisce ulteriore approfondimentio su alcune delle caratteristiche più avanzate di Archetypes. Queste caratteristiche offrono dei tools utili per lo sviluppo dei vostro tipi di contenuto. Questo includerà la creazione di riferimenti, di nuovi widgets, e la trasformazione del contenuto.

Per questo capitolo, è importante conoscere come le modifiche che farete possono essere portati attraverso Plone. Come avete visto precedentemente, avete differenti scenari per il setup del vostro prodotto. Quando effettuate una modifica al vostro prodotto, aiuta conoscere i passi necessari da fare.

Se cambiate qualche cosa in uno skin, giusto eseguendolo in modalità debug vi assicura che le modifiche sono propagati. Se cambiate qualche cosa che passa sul tool portal_actions come azioni od icone, allora avete bisogno di riavviare Plone e di reinstallare il prodotto attraverso Add/Remove Products.

Se cambiate uno schema, allora avete proprio bisogno di riavviare Plone, e tutti le nuove instanze della vostra classe saranno aggiornate in Plone. Comunque, questo riguarda tutte le vecchie instanze del prodotto? Fortunatamente, Archetypes ha previsto un tool di aggiornamento dinamico che naviga attraverso tutte le vecchie instanze del vostro prodotto e li aggiorna al nuovo schema. Nella ZMI, cliccate archetype_tool

Usare Id unici

Il concetto di Id unico è semplice ma è qualche cosa che è stato perso in Zope. Originalmente gli sviluppatori di Zope hanno presupposto di utilizzare il percorso ad un oggetto; sfortunatamente, questo ha mostrato di essere inadeguato. Come semplice esempio, si consideri quello che succede quando qualcuno cambia l'ubicazione di un documento – il vostro unico riferimento a quel documento è stato perso. Un Id unico è un tool veramente utile da avere. Archetypes crea un Id unico su ogni oggetto creato e lo salva nell'oggetto. Lo salva anche in un catalogo separato chiamato uid_catalog.

Potete vedere uid_catalog nella ZMI, ed è come l'oggetto di portal_catalog eccetto che ommette un piccolo pezzo di extra Application Programming Interface (API) avvolto e tutti gli indici che il primo contiene. È abbastanza semplice ora da ottenere un oggetto passando attraverso questo catalogo. Tutto ciò che dovete fare è ricercare nel catalogo il vostro oggetto. Per esempio, il seguente oggetto script (Python) può tirare qualsiasi l'oggetto registrato, se conoscete il relativo UID:

##paramaters=objectId
results = context.uid_catalog(UID=objectId)
return results[0].getObject()

Ma dove è realmente utile è nei riferimenti fra oggetti esistenti. Dite che cercate di riferirvi ad una o più immagini separate con vostro articolo. Queste immagini possono essere immagini caricate da altri utenti da un'altra data, forse parte di un database di immagine. Se queste immagini sono oggetti di Archetypes, allora potrete aggiungere un campo al vostro schema dell'articolo che leggete come segue:

ReferenceField("images"
    allowed_types=("Archetype Images",),
    multivalued=1,
    ),

L'utente ora troverà una casella a discesa di tutti gli oggetti Image di Archetype e sarate capaci di sceglierli. Dietro alle quinte state facendo riferimento all'UID di quel oggetto attraverso il catalogo. Troverete un esempio eccellente sui riferimenti in un prodotto chiamato ACME nel repository CVS di Archetypes presso http://sf.net/projects/archetypes.

Modificare i Widgets

Una domanda comunemente richiesta è, perché questi widget fanno questo? Un altro è, perché questi widget appaiano come questo? Spesso la risposta è qualche cosa come, perché ora – non andate a scrivere proprio i vostri. Siccome i widgets sono quelli che il client vede, questi requisiti sono client orientati. Tutti i widgets sono rappresentati come macro modello di pagina nel File System. Quindi è abbastanza semplice modificare i widgets o farne proprio i vostri. Se cliccate portal_skin

portal_skins Davvero, il termine macro < manca qualcosa qui – Ugo >

La macro view è visualizzata sulla pagina view ed è a sola lettura, di facile uso dall'articolo. La macro edit è quella mostrata sulla pagina di edit, ed è la macro ove un utente edita i dati. La macro di ricerca è chiamata quando state assemblando pagine di ricerca per il codice; qualche volta guardate proprio la macro edit, anche se può non essere. Un campo stringa può essere modificato come un campo stringa e può essere visualizzata come una stringa, ma è ricercabile usando una casella a discesa per selezionare tutte le opzioni disponibile.

Quindi, nel prodotto di esempio, assumiamo che avete un campo stringa che è l'indirizzo e-mail di una persona, e che volete mostrare che questo sia un collegamento e-mail cliccabile. Per questo creerete una nuova macro. In questo caso, non avete bisogno in realtà di sovrascrivere la macro di edit o di search – dopo tutto è giusto una stringa. Quindi, fate un nuovo modello di pagina chiamato email_widget.pt, come segue, che metterà nello skin del vostro prodotto:

<html xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      i18n:domain="plone">
 
  <body>
    <div metal:define-macro="edit">
      <div metal:use-macro="here/widgets/string/macros/edit" />
    </div>
 
    <div metal:define-macro="search">
      <div metal:use-macro="here/widgets/string/macros/search" />
    </div>

Per la vista, avete bisogno di realizzare la stringa mostrata come un collegamento malto che è solamente la semplice rettifica seguente:

    <div class="field" metal:define-macro="view">
        <a href="#" tal:attributes="href string:mailto:${accessor}"
          tal:content="accessor">email</a>
 
    </div>
</body>
</html>

Ora che avete definito un modello di pagina che contiene il vostro codice, potete semplicemente far riferimento al nome del template come la macro nel vostro widget. Nel codice seguente, definite il campo posta elettronica ed un StringWidget come normale. Cambiate poi la vostra macro per usare la vostra bella nuova macro email_template, come così:

StringField('email',
    validators = ('isEmail',),
    widget = StringWidget(
        label='Email',
        macro='email_template'
    )
)

A questo punto state proprio cambiando la macro di un widget esistente. Fare un widget completamente nuovo è solo questione di definire un nuovo widget e quindi registrarlo. Tutti i widgets condividono la stessa classe base. Il seguente è un nuovo modulo chiamato EmailWidget.py che è collocato nella directory ArchExample. Create un nuovo widget e quindi registratelo all’interno del registro. Notate che la proprietà macro del widget (evidenziata) sia settato al valore del template:

from Products.Archetypes.Widget import TypesWidget
from Products.Archetypes.Registry import registerWidget
 
class EmailWidget(TypesWidget):
    _properties = TypesWidget._properties.copy()
    _properties.update({
       'macro' : "email_template",
       'size' : '30',
       'maxlength' : '255',
       })
 
registerWidget(EmailWidget,
    title='String',
    description='Renders a clickable email field',
    used_for=('Products.Archetypes.Field.StringField',)
)

Per includere questo nel vostro articolo, ora potete importare direttamente EmailWidget e potete usarlo senza dovere definire esplicitamente la macro, così come:

from EmailWidget import EmailWidget
 
StringField('email',
    validators = ('isEmail',),
    widget = EmailWidget(
        label='Email',
    )
)
Sviluppare oggetti Folderish

Avete già lavorato molto con gli oggetti folderish in Plone, ma potevate non saperlo. Un oggetto folderish possiede caratteristiche simili ad una cartella od ad una directory, vale a dire che può contenere separati oggetti individuali. Non v’è realmente nulla di speciale in un oggetto folderish - giusto eredita da una certa classe base per offrire le sue proprietà, e nuovi contenuti possono essere aggiunti.

Gli oggetti di Folderish sono utili molte ragioni per costruire. Loro offrono un semplice modo di creare raccolte di oggetti disparati in un'ubicazione. Loro inoltre permettono agli utenti di amministrarere i contenuti usando l’interfaccia utente standard di Plone, senza dover fare niente altro. Generalmente, è [abitudine -ndt] migliore tenere la cartella piuttosto semplice, e la logica dovrebbe essere nei vostro oggetti e nei workflow degli oggetti. Comunque, sempre delle eccezioni a ciò esistono ed un esempio classico è la famiglia dei raccoglitori, CMFCollector e PloneCollector entrambi dei quali sono del tutto oggetti complicati raccoglitori che offrono logica per un gruppo di problemi dei raccoglitore.

Di nuovo, il modo più facile per creare un oggetto folderish è usare Archetypes. Avete visto che c'èra un tipo BaseContent che per maneggiare tutto il lavoro ha avuto bisogno di creare un oggetto nonfolderish. Bene, c'è anche un tipo di contenuto BaseFolder che contiene ogni cosa [necessaria – ndt] per creare una cartella. Più avanti, troverà un schema speciale per le cartelle, da quando folderish obiettano anche di default abbia una descrizione. Fare un folderish dattilografare, solo assicura che cambiamentia le Sue classi vili ed i Vostroi schemi. Per esempio, la più semplice cartella possibilmente è il seguente:

from Products.Archetypes.public import BaseFolder, BaseFolderSchema
 
schema = BaseFolderSchema
 
class SimpleFolder(BaseFolder):
    """A simple folderish archetype"""
    schema = schema
 
registerType(SimpleFolder)

If you're going to store a huge amount of content in a folder, then a folder tends to become inefficient at about 100 objects. That's a rather arbitrary figure that should be taken with a pinch of salt; normal folderish objects are designed to be fast for small numbers of object. If you wanted, you could use a binary tree folder, which stores the objects internally in a more efficient binary tree, rather than a Python dictionary. To use this, just import BaseBTreeFolder and BaseBTreeFolderSchema and use these in your object instead. As far as developing a product is concerned, they work just the same, but unless you put a lot of data into them, you wouldn't likely notice any difference. I've stored more than 100,000 objects in BTreeFolder, and it's always responded well.

Maneggiare contenuto Microsoft Office

Maneggiare contenuto Microsoft Office, come documenti Word e Excell, è una sventura che tutti i sistemi di gestione di contenuto affrontano ad un certo punto. Comunque, questo in realtà è il caso per qualsiasi tipo di contenuto – Microsoft Office, OpenOffice.org, Portable Document Format (PDF), immagini, e così via. Usare queste forme di contenuto sui siti Web di solito causa alcuni problemi; questo è conosciuto bene, chiaramente. Modificare è poco pratico perché cliccando un documento si causa il suo download od, anche peggio, l'apertura nel vostro browser. Quando avete finito, dovete (ri)caricarlo di nuovo sul sito Web che normalmente può voler dire cliccandolo un po' di riaverlo.

Quando il contenuto è on-line, i contenuti non sono ricercabili perché non sono in formato semplice-testo [che – ndt] il catalogo potete capire. Ulteriormente, non potete vedere il contenuto on-line perché di nuovo non è in un formato Web-amichevole.

Avete un paio di soluzioni per risolvere il primo problema di modificare il contenuto. Se di nuovo presumete che la maggior parte dei vostri utenti stia usando Windows, allora usare WebDAV può essere ingannevole in quanto la realizzazione della cartella Web di Microsoft è di qualità discutibile. Invece, External Editor adempie del tutto bene a questa funzione – se Plone può dire ad External Editor che questo è un file Word, lo aprirà in Word.

Come per il resto, bene, Archetypes ha un pacchetto di trasformazione incorporato, chiamato Portal Trasforms, questo si occupa della trasformazione dei tipi di contenuto. Questo può prendere un file in un certo formato e può trasformarlo in HTML che sarà poi catalogato e lo HTML verrà visualizzato all’utente nell'interfaccia utente. Fa questo usando un processo di trasformazione esterno per trasformare i dati e leggere i risultati. Per esempio, se state usando Windows (sul server), poi Portal Trasforms prenderà il documento di Word caricato ed avvierà un oggetto Component Object Model (COM) che lo trasforma.

Tutto questo succede dietro alle quinte; tutto ciò di cui vi dovete preoccupare è di essere sicuri che ogni requisiti per la vostra trasformazione sia installata ed operativa. Potete fare molti tipi diversi di trasformazioni, e ci sono molti modi di trasformare i dati.

La suite di OpenOffice.org offre un’eccellente trasformazione del contenuto di Microsoft, così che se state eseguendolo su una piattaforma non-Microsoft, questo è un modo eccellente di trasformare quel contenuto. Abbiamo usato anche wvWare (http://wvware.sourceforge.net /) piuttosto con successo come un altro modo di trasformare contenuto. Tutti queste opzioni sono disponibili; comunque, loro non sono banali da installare. Una volta che sono installati, le persone di solito risultano soddisfate, trovando trasformazioni di alta qualità come quando usano un server Microsoft.

Raccomandiamo di pensare precisamente quello che volete trasformare prima e di dare poi un sguardo al codice sorgente di Portal Trasforms per vedere se potete trovare una trasformazione che faccia il lavoro per voi.

Setting up un Tipo di contenuto

Ora creeremo un semplice tipo di contenuto per maneggiare un documento Microsoft Word, probabilmente il tipo più comune di contenuto che dovrete amministrare. Per questo esempio, eseguimo la trasformazione su Windows. Comunque, se volete preparare un sistema alternativo, la maggior parte di ciò che segue funziona su Linux. In questo caso, la cosa più facile da fare è usare Windows per installare la vostra instanza Plone. Questo creerà un installazione con tutto i moduli di API Win32 installati e funzionandi. Abbiamo Microsoft Office installato sul server. Avete bisogno quindi di creare un tipo di contenuto, chiamato * WordExample*, per occuparsi dell'esempio. Essenzialmente un unico campo dello schema si occupa del contenuto così che lo schema sembra essere seguente:

schema = BaseSchema +  Schema((
    TextField('body',
              searchable=1,
              required=1,
              primary=1,
              default_output_type='text/html',
              allowable_content_types=('application/msword',),
              widget=RichWidget(label='Body'),
              ),
    ),
    marshall=PrimaryFieldMarshaller(),
    )

L'unica differenza è che avete aggiunto un tipo Multipurpose Internet Mail Extensions (MIME) per il documento Word, application/msword. Per ciascuno tipo di contenuto da essere trasformato, aggiungete un tipo MIME in* allowable_content_types*. Per esempio, se ì volete occuparsi dei documenti di Word e PDF, avrete la seguente linea:

allowable_content_types=('application/msword','application/pdf'),

Questo tipo di contenuto è proprio semplice come potete vedere a questo punto. Ma potete collegare molte cose in questo tipo di contenuto - come una descrizione o molte proprietà. Se state facendo molto lavoro, allora sarebbe anche auspicabile che sia possibile prelevare le informazioni metadata dal documento Word e metterlo come metadata in Plone.

Setting up una trasformazione su Windows

La trasformazione dovrebbe essere settata automaticamente nel tool portal_transforms. Non c'è veramente molto da guardare nel tool; offre soltanto un lista delle trasformazioni che sono disponibile. Una trasformazione ha un lista di tipi MIME entranti che trasformerà (come application/msword) e ll’output che verrà prodotta (come text/html). Ogni trasformazione è un modulo nel File System; in questo caso, potete trovarlo in PortalTransforms/transforms/word_to_html.

Per questa trasformazione da lavorare, tuttavia, dovete eseguire un'utilità per generare i collegamenti COM per Python. Per fare questo, selezionate Start - Plone - Pythonwin e quindi selezionate Tools - COM Makepy Utility. Questo elenca tutte le interfacce COM disponibili; se avete installato Office, vedrete un ingresso per Word in qualche parte della lista. Sul nostro particolare server Windows, questo è chiamato Microsoft Word 9.0 Object Library (8.1). Selezionate questa scelta, e cliccate OK. Pythonwin ora genererà le informazioni adatte. Una volta che avete fatto questo, troverete un messaggio che riguarda di nuovo 'Generating to.. "

Ora potete chiudere Pythonwin e riavviare Plone.

Testare il tipo di contenuto

Per esaminare il vostro tipo di contenuto, avete bisogno di ravviare Plone, assicurarvi che il prodotto sia registrato come al solito, ed installato usando lo schermo Add/Remove Products. Per aggiungere un nuovo documento Word, andate all’interfaccia di Plone e nella casella a discesa selezionate Document Word; è abbastanza ovvio visto che vedrete anche un piccolo logo di Word.

Successivamente, selezionate il vostro file dal File System, e cliccate Salva per caricare il vostro file. Una volta che questo è stato fatto, il file sarà caricato, e sarà portato nella pagina di vista. Questo può prendere un po’ di più di quanto vi aspettate – avete caricato il documento nel server e poi effettuato la trasformazione. Ma sarà portato alla pagina di vista dal vostro tipo di contenuto, e certamente sarà mostrato in HTML, come mostrato in figura 13-4.

../pb2_en/img/3294f1304.png

Figura 13-4. Il file caricato

Ora che è caricato, vorrete modificarlo; per questo, la vostra scommessa migliore è usare External Editor. Se avete installato External Editor sul vostro client locale, cliccate l'icona di matita nell'angolo in alto a destra, e il file si aprirà in Word, come mostra in Figura 13-5. Ora potete alterare e modificare il vostro documento Word. Ogni volta che salvate il file, verrà caricato all’interno di Plone e verrà trasformato.

../pb2_en/img/3294f1305.png

Figura 13-5. Il documento caricato in Word

Andare oltre: scrivere tipi di contenuto in un diagramma UML

Così avete un tipo di contenuto complicato e l’idea di scriverlo a mano vi sta annoiando? Bene, niente paura, perché ArchGenXML è qui! Questo è un prodotto pulito che permette di scrivere il vostro contenuto in un tool di modellizzazione grafico UML e svilupparsi un prodotto dritto da questo. Filippo Auspberg sviluppò ArchGenXML, e Jens Klein ha offerto della documentazione eccellente. Con gentile permesso, riprodurremo alcuni di quei diagrammi qui.

Il tool di modellazione UML deve supportare uno sistema standard Extensible Markup Language (XML) di generazione chiamato XML Metadata Interchange (XMI). Questo tool è stato testato con i seguenti programmi:

  • ObjectDomain (commerciale, con una demo gratis per 30 classi) presso http://www.objectdomain.com
  • ArgoUML (libero) presso http://argouml.tigris.org
  • Poseidon (commerciale, basato su ArgoUML) presso http://www.gentleware.com
  • Sybase Powerdesigner (commerciale, demo download) presso http://www.sybase.com

Ci sono lievi differenti proprietà di esportazione per ognuno di questi, ma se date un sguardo negli esempi di ArchGenXML, vedrete esempi di output dai tools UML. La figura 13-6 mostra un progetto di classe che espone alcuni oggetti: room, person project, resource e task. Ci sono relazioni fra tutti questi oggetti, e c'è regolare codice Python specificato su alcuni degli oggetti.

../pb2_en/img/3294f1306.png

Figura 13-6. Un esempio complesso di ArchGenXML

Il modo più rapido di esaminare questo è andare nella cartella di ArchGenXML sul vostro File System che avete ottenuto dall'originale installazione e poi modificatelo nella cartell


Andy McKay: The Definitive Guide to Plone. Apress 2004
This online version was generated using the 'PloneBook' product from docs.neuroinf.de/products.
It was last updated by
lallo on 2005-04-09 07:08 from the cvs source using
svn export http://docit.bice.dyndns.org/Plone/PloneBook2/it LibroPlone.

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: