Archetypes Developer Manual
Note: Return to reference manual view.
1. Introduction
1.1. What is Archetypes?
Archetypes is a framework for developing new content types for a Plone project. Most content management projects involve introducing new types of content, which in the non-trivial case requires an informed understanding of how Zope and the CMF work. Archetypes provides a simple, extensible framework that can ease both the development and maintenance costs of CMF content types while reducing the learning curve for the simpler cases.
Compared to building content types using the stock CMF (through subclassing), Archetypes gives you the following advantages:
- automatically generates forms and views;
- provides a library of stock field types, form widgets, and field validators;
- allows defining custom fields, widgets, and validators;
- automates transformations of rich content;
- a built-in reference engine that gives the ability to link two objects together with a relation; such a "link" from a given object to another one is a Python object called a reference.
Since Plone 2.1, Archetypes has become the de-facto way of developing new content types, and a majority of third party products that are released these days use Archetypes.
1.2. What is ATContentTypes?
One of the major changes introduced in Plone 2.1 was that the core content types (Page, Image, etc) were changed from being based on stock CMF types, to using Archetypes. The new core types are housed in the ATContentTypes product.
ATContentTypes introduces a number of base classes and tools that provide common "Plone-ish" behaviour. This includes things like support for the "display" menu and the "more..." menu and restrictions for the "add item" menu.
You can use ATContentTypes' base classes and tools in your own products. The RichDocument tutorial covers the core techniques, and is probably a good place to go when you have finished this reference. Typically, these are most useful if you are building content types that are really content - along the lines of Plone's built-in content types. If you are using Archetypes to build things that are more oriented to functionality (like, say, to build an issue tracker or a forum), then ATContentTypes may not be as useful as starting point.
2. A simple AT Product
2.1. Introduction
In this part of the manual, we discuss a sample AT Product to put the theory of Archetypes into practice. We will be building a product called InstantMessage, which can be used by members with specific rights to add instant messages for other members. However, as you may have guessed, this is more a learning example than a usable product for a real website application.
What is a Product ? A product - a Zope product to be precise - is a third party add-on that can be integrated to provide additional functionality. It is a code package written using the Python language and conventions.
In order to understand this section you will need to have some prior knowledge of working on the file system and programming protocols common to Python and Zope.
InstantMessage features the following CMF and Archetypes capabilities:
- basic fields and widgets;
- defining and using a vocabulary for a field with a selection widget;
- defining specific "Add" permissions for the contents.
The core of the product can be downloaded here: http://plone.org/products/instantmessage
2.2. AT product layout
Following Zope, Plone and AT's conventions, our InstantMessage product layout will look like this:
- README.txt
- __init__.py
- configure.zcml
- config.py
- permissions.py
- content
- __init__.py
- message.py
- profiles
- default
- skins
- instantmessage
- tests
- __init__.py
- base.py
- test_setup.py
What is the purpose of these files and directories?
- __init__.py: The usual "Python package" initialization module;
- configure.zcml: Using Zope's new Configuration Markup Language (ZCML), this file configures the services or behaviour the Zope server needs to load at startup;
- config.py: Provides configuration variables for the product;
- permissions.py: Provides permission definitions for the content types;
- content: Contains the modules providing the implementation of the content types.
In this case, it contains the message.py file where the
'InstantMessage' class should be defined;
- profiles/default:
Contains a set of XML files that are needed to provide the settings that will be used by Plone's Quick-Installer tool when installing the product within Plone; this is what we call an Extension Profile, an artifact of Zope CMF's GenericSetup technology. Note that this replaces the old way of doing based on the Extensions/Install.py module.
- skins: The container of the subskin directory(ies). Here it contains only one directory where specific UI elements for the InstantMessage (images, templates, scripts) could be added later;
- tests: Contains the unit tests code for the product.
Now we will go through the files one by one and add what we need to produce our Instant Message content type.
2.3. The permissions module
First, we import the standard useful modules:
from Products.CMFCore.permissions import setDefaultRoles
from Products.Archetypes.atapi import listTypes
from config import PROJECTNAME
In this module, we need to define the "Add" permission for the Instant Message type, and set it to the default roles:
# Add an Instant Message
ADD_CONTENT_PERMISSION = 'InstantMessage: Add InstantMessage'
# Assign default roles
setDefaultRoles(ADD_CONTENT_PERMISSION, ('Owner', 'Manager',))
The reason the variable here is UPPERCASED is that it should be treated like a constant, and this makes them easy to spot.
We recommend using the standard way of naming permissions: '<ProductName>: <Permission>'. This will group the related permissions together within the ZMI (Security tab), and allow the Administrator to recognize which permissions belong to which Product.
Note that, unless you have an advanced case which needs custom security settings, you don't need to define your own permissions for the "edit" and "view" of the content. In this simple case you will just reuse, in the modules where needed, the generic permissions defined in CMFCore.permissions: "View", "Modify portal content"...
2.4. The configuration module
First we have to import a class from Archetypes:
from Products.Archetypes.public import DisplayList
Displaylist is a data container we use when displaying
pulldowns/radiobuttons/checkmarks with different choices. Let's say we wanted
priorities on our instant messages, and we wanted those to be High, Normal
and Low. We will specify these later in the file.
The next two lines set the project (Product in Zope) name, and point to the
skin directory. PROJECTNAME should reference the name of the package: InstantMessage.
PROJECTNAME = "InstantMessage"
SKINS_DIR = 'skins'
The next line sets a GLOBALS reference point, calling Python's 'globals' function:
GLOBALS = globals()
This is used later during the product's installation phase for things like finding the Product directory (see the Install.py later).
Now we are done with the generic setup. Then we need to specify our 'Priority' pulldown. It should look like this, using the DisplayList utility class that Archetypes has provided for exactly that purpose:
MESSAGE_PRIORITIES = DisplayList((
('high', 'High Priority'),
('normal', 'Normal Priority'),
('low', 'Low Priority'),
))
Python notes:
The reason for double parantheses is that DisplayList is a class that you pass a tuple of tuples to.
2.5. The startup module
process_types is useful to get the product's content types,
associated constructors, and Factory Type Information (FTI) data structures, while listTypes can be used to list the types available in the product.
from Products.Archetypes.atapi import process_types, listTypes
Python notes:
Factory Type Information (FTI): Part of a CMF portal's configuration, the FTI for a content type is the data structure that holds the information needed to expose a content type within the portal. From the integrator's perspective, the FTI is the object (Factory-based Type Information object) within the portal_types component that tells CMF and Plone how to create a content from the type and how to display it.
How exactly does 'listTypes' work: See those registerType() calls in your content type modules? Notice how we also import those modules (but do nothing with the import) in the 'content' package's __init__.py. The registerType() call tells AT about the type so that listTypes() can find it later.
The next two import lines you have to add are needed to talk to the CMF architecture, and to register Directory Views (or subskins) inside Plone.
from Products.CMFCore import utilsOne of the important import steps : we use a single line to import everything that is defined in the content sub-package, i.e. all its modules (even though it currently only contains one module):
from Products.CMFCore.DirectoryView import registerDirectory
from content import *
Python note:
This is a useful shortcut for rapid development; we don't need to traverse the package to import things one by one.
Next step is to import the configuration details and the "Add" permission reference for the product:from config import SKINS_DIR, GLOBALS, PROJECTNAME
from permissions import ADD_CONTENT_PERMISSION
The next line registers the skins and global directories as File System Directory Views in the CMF:
registerDirectory(SKINS_DIR, GLOBALS)
Now for the real action. You define a function that is required by Zope and CMF internals to initialize our content type(s):
def initialize(context):
The first part of the code of this function generates the content types, the constructors and the Factory-based Type Informations (or FTIs) required to make your types work with the CMF:
content_types, constructors, ftis = process_types(
listTypes(PROJECTNAME),
PROJECTNAME)
The second part instantiates an object of the class ContentInit (from CMFCore),
and registers your types in the CMF:
utils.ContentInit(
"%s Content" % PROJECTNAME,
content_types = content_types,
permission = ADD_CONTENT_PERMISSION,
extra_constructors = constructors,
fti = ftis,
).initialize(context)
2.6. Permissions and startup modules - Take 2
Handling permissions for several content types
There is a better, advanced way to write this code so that it still works even if you define several content types (in the content subpackage). This technique, introduced by Ben Saller in his "Bricolite" example product (which you can find in the Collective SVN), is useful to define a dictionary containing several definitions (ADD_CONTENT_PERMISSIONS), making use of Archetypes 'listTypes' function:# Defining several Add permissions
ADD_CONTENT_PERMISSIONS = {}
types = listTypes(PROJECTNAME)
for atype in types:
permission = "%s: Add %s" % (PROJECTNAME, atype['portal_type'])
ADD_CONTENT_PERMISSIONS[atype['portal_type']] = permission
# Assign default roles
setDefaultRoles(permission, ('Owner', 'Manager',))
The developer is encouraged to use this improved code. We need to update the startup module based on it.
Improving the __init__ module
The first change needed here is to import ADD_CONTENT_PERMISSIONS instead of ADD_CONTENT_PERMISSION:from permissions import ADD_CONTENT_PERMISSIONSAgain, thanks to Ben Saller, we have a way to register each content type (which is useful when you later augment your product with additional types) with its own permission:
def initialize(context):
content_types, constructors, ftis = process_types(
listTypes(PROJECTNAME),
PROJECTNAME)
# We want to register each type with its own permission,
# this will afford us greater control during system
# configuration/deployment (credit : Ben Saller)
allTypes = zip(content_types, constructors)
for atype, constructor in allTypes:
kind = "%s: %s" % (PROJECTNAME, atype.portal_type)
utils.ContentInit(
kind,
content_types = (atype,),
permission = ADD_CONTENT_PERMISSIONS[atype.portal_type],
extra_constructors = (constructor,),
fti = ftis,
).initialize(context)
Python notes:
We can use the "ADD_CONTENT_PERMISSIONS[atype.portal_type]" construct because ADD_CONTENT_PERMISSIONS references a dictionary in which the keys are the potential content types names.
The zip() function is a Python built-in that pairs up elements of two lists. In this case, "allTypes" will be a list of tuples containing a content type from "content_types" and the corresponding constructor from "constructors".
2.7. The content package and its modules
Our 'content' directory contains 2 modules:
- the usual __init__ module that makes it a Python package,
- the message module where we will define the 'InstantMessage' class.
The message module
We need to use a selection of classes and/or functions provided by the core of our codebase (i.e. CMF and Archetypes). Right now, the most important ones are Archetypes' base schema classes. So we import them:
from Products.Archetypes.atapi import BaseSchema, Schema
The heart of an Archetype is its Schema, which is a sequence of fields. Archetypes includes three stock schemas: BaseSchema, BaseFolderSchema, and BaseBTreeFolderSchema. All three include two fields, id and title, as well as the standard metadata fields. BaseSchema defines a normal content type, BaseFolderSchema defines a folderish content type (object can contain other objects), and BaseBTreeFolder is for folders which need to handle hundreds or thousands of objects (even up to millions).
The Schema works like a definition of what your object will contain and how to present the information contained. When Zope starts up, during product initialization, Archetypes reads the schema of the registered classes and "automagically" generates methods to read (the accessor) and change (the mutator) each of the fields defined.
Next, we import some of the widgets we need for displaying our content type:
from Products.Archetypes.atapi import SelectionWidget
from Products.Archetypes.atapi import RichWidget
A SelectionWidget is a UI widget that will let you choose one of many choices, a RichWidget enables Plone's currently selected Visual Editor (WYSIWYG editors like Kupu or FCKEditor).
Next up, we import BaseContent (which we inherit from with our Content Type, if it had been folderish, we would have imported and inherited from BaseFolder).
from Products.Archetypes.atapi import BaseContent
The registerType function is needed to initialize our content type later, so we import it here.
from Products.Archetypes.atapi import registerType
You also can import all the fields, widgets and classes made publicly available by Archetypes. Note that this is considered bad style by most Python programmers (importing * from a module), but this doesn't mean it can't be done and, of course, it makes life a lot easier: it makes a lot of stuff available to our module, although we are only going to use a small amount of it:
from Products.Archetypes.atapi import *
We also need to import the CMF permissions module ; later (see below) we use some of the permissions it contains for protecting our content object's actions:
from Products.CMFCore import permissionsFinally, we import things internal to our product, mainly the useful things we have in the config module (such as PROJECTNAME and our message priorities):
from Products.InstantMessage.config import PROJECTNAME
from Products.InstantMessage.config import MESSAGE_PRIORITIES
Now, we have everything we need to start building the schema itself. We start out by copying the BaseSchema (which basically includes the object id and the Dublin Core metadata attributes), and we extend it by adding our specific fields.
schema = BaseSchema.copy() + Schema((
StringField('priority',
vocabulary = MESSAGE_PRIORITIES,
default = 'normal',
widget = SelectionWidget(label = 'Priority'),
),
TextField('body',
searchable = 1,
required = 1,
allowable_content_types = ('text/plain',
'text/structured',
'text/html',),
default_output_type = 'text/x-html-safe',
widget = RichWidget(label = 'Message body'),
),
))
Python notes:
To instantiate a schema object, you pass 'Schema' a tuple of field objects.
We define the body of the InstantMessage object using a RichWidget, so the user can use formatting with a WYSIWYG editor.
Note that the full list of available Fields and Widgets can be found in the Fields section at the end of the manual.
The last step is to create the class for the InstantMessage itself. It inherits from BaseContent, which automatically gives its 'id' and 'title' attributes, and the entire Dublin Core set (Title, Description, Creator, CreationDate, etc):
class InstantMessage(BaseContent):
""" An Archetype for an InstantMessage application """
Then we assign standard attributes to the class:
- the schema that we just defined using the schema attribute
- the meta_type, portal_type, and archetype_name attributes
schema = schema
meta_type = portal_type = 'InstantMessage'
archetype_name = 'Instant Message'
In addition, Archetypes provides a special attribute that is useful for generating the content object's name (the Id in Zope jargon) based on the Title the user provides when creating the content. It is a good idea to add it if you want the object Id, which appear at the end of a page URL, to not look like 'InstantMessage.2006-12-01.2244'.
_at_rename_after_creation = TrueThe CMF also allows you to define the "content tabs" for the object class. These are the tabs that appear in Plone's user interface to help the user to quickly access the obj
The CMF also allows you to define the "content tabs" for the object class. These are the tabs that appear in Plone's user interface to help the user to quickly access the object's data and features. You define them using the 'actions' attribute, which you set using a tuple of Python dictionaries, a dictionary containing the keys 'id', 'name', 'action' and 'permissions' for each tab.
Here, we define the usual "View", "Edit" and "Properties" tabs:
actions = ({
'id' : 'view',
'name' : 'View',
'action' : 'string:${object_url}',
'permissions' : (permissions.View,)
},
{
'id' : 'edit',
'name' : 'Edit',
'action' : 'string:${object_url}/edit',
'permissions' : (permissions.ModifyPortalContent,),
},
{
'id' : 'metadata',
'name' : 'Properties',
'action' : 'string:${object_url}/properties',
'permissions' : (permissions.ModifyPortalContent,),
},
)
Let's explain some of the details here:
'object_url' is a variable that references the object's absolute URL.
The 'action' key of the dictionary is used to define the URL of the page; the 'edit' or 'properties' part of the URL is an alias that points to the template used to provide the page. See below for the aliases definition.
- The "View" action will be seen only if the user has the CMF's 'View' permission in the context of an Instant Message object.
- The "Edit" and "Properties" actions will be seen only if the user has the CMF's 'Modify portal content' permission in the context of an Instant Message object.
aliases = {
'(Default)' : 'instantmessage_view',
'view' : 'instantmessage_view',
'edit' : 'base_edit',
'properties' : 'base_metadata',
}With such a definition, what you are telling the CMF API is:- The content's default view is provided by a custom template called 'instantmessage_view', to be added later. The result of that setting is that when an user types in an Instant Message object URL through the browser, he gets the object presented with the specified template. In addition, 'view' is an alias for that template, which results in the fact that an user gets the object presented with the template if he types in the object URL completed with '/view'.
- 'edit' is the alias for Archetypes 'base_edit' built-in template.
- 'properties' is the alias for Archetypes 'base_metadata' built-in template.
CMF notes:
'index.html', 'gethtml', and 'mkdir' are other possible aliases but it is not useful to override them for the InstantMessage case.
The 'gethtml' alias provides a hook for Zope (and Plone) 'manage_FTPget' function, used by some contentish types for WebDAV/FTP support, i.e. the code could allow downloading a file (such as HTML, iCalendar, etc) with a WebDAV/FTP request.
The 'mkdir' alias provides a hook for the 'manage_addFolder' function, used by some folderish types for WebDAV/FTP support, i.e. you could create a subfolder of the folder with a WebDAV/FTP request.
Finally, we are ready to activate the content type in Archetypes internal types registry. This is done using the 'registerType' function.
registerType(InstantMessage, PROJECTNAME)
Congratulations! You have just created your first Archetype! It allows you to handle the content of an instant message with Zope-based persistent objects which:
- can be added within your Plone site,
- published by the Zope Publisher, which means you can visit them via their URLs, etc...
- searched since they are automatically indexed,
- etc...
But wait ! There is still some work left. Also you will have some final packaging work to do to ease installation of the product within your Plone site.
The __init__ module
The trick here is to simply import the message module so that all the code of that module gets interpreted as soon as the Python interpreter initializes the package.import message
2.8. Adding a custom view to the skin
<html metal:use-macro="here/main_template/macros/master"
i18n:domain="plone" >
<body>
<div metal:fill-slot="main"
tal:define="priority here/getPriority;
priority_color python:test(priority == 'high', 'red', priority == 'low', 'green', '')" >
<h1 tal:content="context/Title"
tal:attributes="style string:color:$priority_color" >
Title
</h1>
<p tal:content="structure here/getBody" />
<div class="documentByLine">
Message by <span tal:content="context/Creator" />
with <strong tal:content="priority" /> priority.
-
<span tal:replace="python:here.toLocalizedTime(context.CreationDate(),long_format=1)" />
</div>
</div>
</body>
</html>
You will notice that this page template is referenced from the aliases you saw in the message.py file, where the content type was defined, as the "(Default)" and "view" aliases. This is how Plone knows to invoke this template when a user tries to view your content object.
2.9. Installing the product
In this part, you will provide the code to be executed when the integrator "adds", i.e. installs, the InstantMessage product to the Plone site. This aspect of the product code is called the "Extension Profile" (or "Setup Profile") and is managed under the hood by a machinery called GenericSetup.
For more about GenericSetup, its possibilities, and how a developer uses it, read the tutorial available at http://plone.org/documentation/tutorial/genericsetup.
The setup profile files (profiles/default)
The setup profile is composed of a set of XML files containing setup declarations.
First, we provide the files needed for adding the types to CMF's types registry (portal_types): types.xml and types/InstantMessage.xml.
In types.xml, within the <object name="portal_types" ... /> element, add the setup code for the type(s) you want to install:
<?xml version="1.0"?>
<object name="portal_types" meta_type="Plone Types Tool">
<property
name="title"> Controls the available content types in your portal </property>
<object name="InstantMessage"
meta_type="Factory-based Type Information"/>
</object>
In types/InstantMessage.xml, add the code for the InstantMessage "Factory Type Information" object:
<?xml version="1.0"?>
<object name="InstantMessage"
meta_type="Factory-based Type Information"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<property name="title"> Instant Message</property>
<property
name="description"> A sample type (InstantMessage) discussed in the AT Developer Manual.</property>
<property name="content_icon"> document_icon.gif</property>
<property name="content_meta_type"> InstantMessage</property>
<property name="product"> InstantMessage</property>
<property name="factory"> addInstantMessage</property>
<property name="immediate_view"> instantmessage_view</property>
<property name="global_allow"> True</property>
<property name="filter_content_types"> True</property>
<property name="allowed_content_types"/>
<property name="allow_discussion"> False</property>
<alias from="(Default)" to="instantmessage_view"/>
<alias from="edit" to="base_edit"/>
<alias from="properties" to="base_metadata"/>
<alias from="view" to="instantmessage_view"/>
<action title="View" action_id="view" category="object" condition_expr=""
url_expr="string:${object_url}/view" visible="True">
<permission value="View"/>
</action>
<action title="Edit" action_id="edit" category="object" condition_expr=""
url_expr="string:${object_url}/edit" visible="True">
<permission value="Modify portal content"/>
</action>
<action title="Properties" action_id="metadata" category="object"
condition_expr="" url_expr="string:${object_url}/properties"
visible="True">
<permission value="Modify portal content"/>
</action>
</object>
We also need the file useful for setting the type against Plone's factory tool (portal_factory): factorytool.xml. This is needed so that when a user adds a content object and then clicks Cancel in the edit form, a stale object won't be lying around.)
<?xml version="1.0"?> <object name="portal_factory" meta_type="Plone Factory Tool"> <factorytypes> <type portal_type="InstantMessage"/> </factorytypes> </object>
Since we have a "CMF layer" or skin component to install, we also add a skins.xml file with the following code:
<?xml version="1.0"?>
<object name="portal_skins" meta_type="CMF Skins Tool">
<object name="instantmessage" meta_type="Filesystem Directory View"
directory="Products.InstantMessage:skins/instantmessage"/>
<skin-path name="*">
<layer name="instantmessage" insert-after="custom"/>
</skin-path>
</object>
Registering our setup profile
We need the following code snippet in the configure.zcml file for loading that extension setup profile:
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
i18n_domain="instantmessage" >
<genericsetup:registerProfile
name="InstantMessage"
title="InstantMessage"
directory="profiles/default"
description="Extension profile for InstantMessage sample AT content type."
provides="Products.GenericSetup.interfaces.EXTENSION"
/>
</configure>
Restarting Zope
Now that you have a first version of your product ready to be tested, you need to (re)start Zope.
Note that you need to ensure that Zope can access your files. One solution (applicable to Unix systems) is to always do a chown (chown -R zope.zope, presuming Zope runs as user 'zope' in group 'zope') in your 'Products' directory after having worked on any product. Once the permissions are in order, you need to restart Zope.
Quick-installing the product
Back in the Plone configuration (or Plone control panel), when you visit the "Add/Remove Products" interface or the portal_quickinstaller tool through the ZMI (at the root of the site), you can see the product show up under the category of "installable products".
Select and click the button to install the product. If everything goes fine, the product should be installed, and you're ready to start using it!
2.10. Basic integration tests
To build high-quality software, you must provide automatic tests - often known as "unit" tests (though tests for Archetypes products tend to be "integration" tests, strictly speaking).
The tutorial on testing and test-driven development is essential reading if you want to write high-quality software (and you don't know the techniques it advocates already). Please refer to it for details.
The InstantMessage product contains basic tests that prove that the product is properly installed, that it registered its types, and that an Instant Message can actually be instantiated. If it contained more functionality, there would have been more tests, but even simple integration tests like this can be surprisingly useful - if you accidentally broke the content type with some change, you'd notice that it failed to install or instantiate.
The tests are in the "tests" directory. The file "base.py" contains some base classes that are used for tests, to ensure the site is properly set up:
from Testing import ZopeTestCase
# Let Zope know about the products we require above-and-beyond a basic
# Plone install (PloneTestCase takes care of these).
ZopeTestCase.installProduct('InstantMessage')
# Import PloneTestCase - this registers more products with Zope as a side effect
from Products.PloneTestCase.PloneTestCase import PloneTestCase
from Products.PloneTestCase.PloneTestCase import FunctionalTestCase
from Products.PloneTestCase.PloneTestCase import setupPloneSite
# Set up a Plone site, and quick-install the relevant products
setupPloneSite(products=('InstantMessage',))
class InstantMessageTestCase(PloneTestCase):
"""Base class for integration tests.
This may provide specific set-up and tear-down operations, or provide
convenience methods.
"""
The actual tests are in "test_setup.py":
from base import InstantMessageTestCase
class TestProductInstall(InstantMessageTestCase):
def afterSetUp(self):
self.types = ('InstantMessage',)
def testTypesInstalled(self):
for t in self.types:
self.failUnless(t in self.portal.portal_types.objectIds(),
'%s content type not installed' % t)
def testPortalFactoryEnabled(self):
for t in self.types:
self.failUnless(t in self.portal.portal_factory.getFactoryTypes().keys(),
'%s content type not installed' % t)
class TestInstantiation(InstantMessageTestCase):
def testCreateInstantMessage(self):
self.folder.invokeFactory('InstantMessage', 'im1')
self.failUnless('im1' in self.folder.objectIds())
def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()
suite.addTest(makeSuite(TestProductInstall))
suite.addTest(makeSuite(TestInstantiation))
return suite
To run these tests under Plone 2.5 on Zope 2.9, you can do:
./bin/zopectl test -m Products.InstantMessage
You may see output like:
Ran 3 tests with 0 failures and 0 errors in 0.119 seconds.
If there was an error with one or more of the tests, you'd be told here!
Please refer to the testing tutorial for more about writing tests - and writing good tests - and how to run them.
3. Fields
3.1. Overview
Archetypes Fields - A Simple Explanation
Archetypes provides a robust framework for storing data attributes on content objects. This framework consist of a number of Fields stored in a container called a Schema. Fields are simply specialized Python classes that allow you to store and retrieve data associated with an Archetypes object.
Fields provide a few functionalities. First, there are specialized field types for strings, lists of strings, integers, floating-point numbers, etc., that allow special handling of fields based on the type of data stored.
Some Definitions
Before we go diving in, let's define some often-used terms:
- Field
- an Archetypes Field. This refers to an instance of a Field class defined in a Schema.
- Schema
- the "container" that Archetypes uses to store fields.
- Schemata
- a named grouping of fields. One Schema can have many schematas.
- AT
- abbreviation for Archetypes.
Some Pre-Requisites
The following pages assume that you have a solid working knowledge of Python.
Fields, Classes, and Objects
In Archetypes, Fields are Python objects contained within a Schema. A Field is defined once for an Archetypes class. This single Field instance is used for every instance of that class. Therefore, the relationship between Field instances and classes is described as such: "A field instance belongs to exactly one class."[1] A class, however, can have many different Field instances. Furthermore, every instance of an AT class uses the same set of Fields. AT objects themselves do not contain unique Fields.
[1]In some strange cases, this may be untrue, where the Schema from a base class is used directly in a new class without copying. In general, this is unwise and should be avoided.
3.2. Fields Reference
Topics |
||
|---|---|---|
|
|
||
Common Field Attributes
These attributes are common to nearly all fields. Field-specific attributes follow, and are listed by field. Particular fields have different defaults, types, and some other specialized attributes.
| Name | Description | Possible Values | Default |
|---|---|---|---|
| accessor | The name of a class method that will return the value of the field. Use this to
change how the field is retrieved. If you don't provide a custom method
name here, a default accessor, named getYourFieldName, is going to be created
that just returns the value of the Field. |
A class method name; for example, specialGetMethod | None |
| default |
The default value for the field. |
Type should be appropriate to the field. |
None |
| default_method |
The name of a class method returning a value for the field. | A class method name; for example, getSpecialDescription. |
None |
| edit_accessor | The name of a class method that returns the raw value of a field. | Any method name (for example, rawGetMethod). |
None |
| enforceVocabulary | Determines whether or not values outside the vocabulary will be accepted.
If True, Archetypes will validate input for the field against the vocabulary.
Only values already in the vocabulary will be accepted. |
True or False. |
False |
| index (Plone < 3 only) |
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 actual index will be on the field accessor, typically "getFieldName".) Ignored in Plone 3+; use GenericSetup profile for similar functionality. |
The name of any index, such as KeywordIndex or KeywordIndex:schema. |
None |
| index_method | May be used to specify the method called when indexing a field. Use '_at_accessor' to use the default accessor, '_at_edit_accessor' to use the edit accessor, or the name of a method returning the value to be indexed. | _at_accessor, _at_edit_accessor, getIndexAccessor and getIndexAccessorName |
_at_accessor |
| languageIndependent |
Flag for Fields that are independent of the language, such as dates. True tells LinguaPlone that no translation is necessary for this field. | True or False | False |
| isMetadata |
Marks metadata fields. This is currently only needed as a convenience for the filterFields method of Schema. Fields marked as metadata are not displayed in the uncustomized base view. | True or False | False |
| mode |
The read/write mode of field, as a string; the default is to be read and write.
Accessors will not be created without the read mode, and Mutators will not be created without the write mode. |
For read only: r, for write only: w, for read and write: rw. |
rw |
| multiValued |
Set this to True if the field can have multiple values. This is the case for fields like multiple-selection lists that allow the selection of multiple values. | True or False. |
False |
| mutator |
The string name of a class method that changes the value of the Field. If you don't provide a special method name here, a default mutator is generated with the name 'setYourFieldName' to simply store the value. | A class method name; for example, specialSetMethod. |
None |
| name | A unique name for this field.
Usually specified as the first item in the field definition.
|
Any string. Strongly recommended: lowercase, no punctuation or spaces,
conforming to standard Python identifier rules.
For example, description, user_name, or coffee_bag_6. |
No default. |
| primary | If True, this will be the field that used for 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 set this for the main body attribute. Only used for TextField and FileField field types. | True or False | False |
| read_permission |
The permission required for the current user to allowed to view or access the field. Only useful if the read mode is activated. This read permission is checked when rendering the widget in read mode. | A permission identifier imported from Products.CMFCore.permissions | View |
| required |
Specifies that some value for this field required. | True or False. | False |
| schemata |
Use named schematas to organize fields into grouped views. | A short string that labels the group. |
default |
| searchable |
Specifies whether or not the field value will be indexed as part of the SearchableText for the content object. SearchableText is what is checked by the portal's main search. | True or False. | False |
| storage |
The storage mechanism for the field. 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). |
AttributeStorage |
| type |
Provided by the field class.. Should never be changed in a Schema. | None |
None |
| validators |
A list or tuple of strings naming validators that will check field input.
If you only have one validator, you may specify it as a string. Validators may also be instances of a class implementing the IValidator interface from from Products.validation.interfaces.IValidator. Providing a class instance allows you more flexibility as you may set additional parameters. Validators are checked in order specified. |
The names of validators registered via Products.validation; for example, isEmail. | () |
| vocabulary |
Provides the values shown in selection and multi-selection inputs. This may be specified as a static list or as the name of a class method returning the choice list. (In Plone 3, it may also be a Zope 3 vocabulary-factory vocabulary.) | A list of strings (in which case keys and values will be the same); a list of 2-tuples of strings [("key1","value 1"),("key 2","value 2"),...]; a Products.Archetypes.utils.DisplayList. Or, the name of a class method returning any of the above. | () |
| widget | The widget that will be used to render the field for viewing and editing.
See the widget reference for a list of available widgets. |
An instance of a widget; for example, StringWidget(). |
StringWidget() |
| write_permission |
The permission required for the current user to edit the field value. Only interesting if the write mode is activated. The write permission is checked when rendering the widget in write mode. | A permission identifier imported from Products.CMFCore.permissions | ModifyPortalContent |
Standard Fields
BooleanField
Simple storage of True or False for a field.
Standard properties| Name | Type | Default | Description | example values |
|---|---|---|---|---|
| widget | widget | BooleanWidget | Implemented as a check box. | |
| default | boolean | False |
|
|
| type | boolean |
|
|
Note: The required attribute for the boolean field is often confusing. It does not require that the box be checked. Use a validator if you need to require the box be checked.
ComputedField
Read-only field, whose content cannot be edited directly by users, but is
computed instead from a Python expression. For example, it can be the result of
an operation on the contents from some other fields in the same schema,
e.g. calculating the sum of two or more currency amounts, or composing a
full name from first name and surname.
This field is usually not stored in the database, because its content is
calculated on the fly when the object is viewed.
| Name | Type | Default | description | some possible values |
|---|---|---|---|---|
| widget | widget | ComputedWidget | ||
| storage | storage | ReadOnlyStorage | |
|
| type | computed | |
||
| mode | string | r | |
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| expression |
|
Evaluated on the object to compute a value. | |
CMFObjectField
Used for storing values inside a CMF Object, which can have workflow. Can only be used for BaseFolder-based content objects.
Standard properties| Name | Type | Default | description | some possible values |
|---|---|---|---|---|
| widget | widget | FileWidget | ||
| storage | storage | ObjectManagedStorage | |
|
| type | object | |
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| portal_type | File |
|
|
|
| workflowable | True |
|
|
|
| default_mime_type | application/octet-stream |
|
|
DateTimeField
Used for storing dates and times.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | CalendarWidget |
|
|
| default | DateTime |
|
|
|
| type | datetime |
|
|
Note: The default for the DateTimeField needs to be specified as a DateTime object. If you need to set the current date/time as the default, you'll need to use the default_method attribute to specify a class method returning the current date/time as a DateTime object.
FileField
Storage for large chunks of data such as plain-text files, office-automation documents, and so on.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | FileWidget | ||
| default | string |
|
|
|
| type | file |
|
|
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| primary | False |
|
|
|
| default_content_type | application/octet |
|
|
|
| primary | boolean | False | Set this True to mark the field as primary for FTP or WebDAV. |
Note: File field values are stored as strings. It's a common practice to use streams to read/write the values as if they were files.
FixedPointField
For storing numerical data with fixed points.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | DecimalWidget | ||
| validators | validators | isDecimal |
|
|
| default | string | 0.00 |
|
|
| type | fixedpoint |
|
|
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| precision | 2 |
|
|
FloatField
For storing numerical data with floating points.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| default | string | 0.0 | |
|
| type | float |
|
|
ImageField
Stores an image and allows dynamic resizing of the image.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | ImageWidget | ||
| default | string |
|
|
|
| type | image |
|
|
|
| allowable_content_types | tuple of MIME strings | Specifies the types of images that will be allowed. | ('image/gif','image/jpeg','image/png') | ('image/jpeg','image/png') |
Note: Image field values are stored as strings. It's a common practice to use streams to read/write the values as if they were files.
Special properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| original_size | tuple (w,h) | None | The size to which the original image will be scaled. If it's None, then no scaling will take place; the original size will be retained. Caution: the aspect ratio of the image may be changed. | (640,480) |
| max_size | tuple (w,h) | None | If specified then the image is scaled to be no bigger than either of the given values of width or height. Aspect ratio is preserved. Useful to prevent storage of megabytes of unnecessary image data. | (1024,768) |
| sizes | dict | {'thumb':(80,80)} | A dictionary of scales in which the image will be available. Dictionary entries should be of the form 'scaleName':(width,height). | { 'mini' : (80,80), 'normal' : (200,200), 'big' : (300,300), 'maxi' : (500,500)} |
| pil_quality | integer | 88 | A JPEG quality setting (range 0 to 100). Lower numbers yield high compression and low image quality. High numbers yield low compression and better quality. | 50 (a medium quality) |
Using Image Scales
To display the original image (possibly rescaled if you used original_size or
max_size attributes), you may use a URL like:
http://url_of_content_object/imageFieldName
as the SRC attribute of an IMG tag where url_of_content_object is the
URL of the content object and imageFieldName is the name
of the image field.
To display one of the scales, use a URL like:
http://url_of_content_object/imageFieldName_scale
where scale is one of the keys of the sizes dictionary.
Attention: The direct attribute access as shown above works only together with AttributeStorage, which will be used by default. To avoid heavy memory consumption on sites with many images it is recommended to use AnnotationStorage for the ImageField.
You may also generate a ready-to-insert IMG tag with the python code:
obj.getField('image').tag(obj, scale='mini')
if obj is your content object, image the name of your image
field, and mini the name of your scale.
You may rescale to other sizes than those in the sizes field attribute with code like:
obj.getField('image').tag(obj, height=480, width=640, alt='alt text',
css_class='css_class_selector', title='html title attribute')
IntegerField
For storing numerical data as integers.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | IntegerWidget |
|
|
| default | integer | 0 |
|
|
| type | integer |
|
|
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| size | 10 | Sets the size of the input field. | |
LinesField
Used for storing text as a list, for example a list of data such as keywords.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | LinesWidget | ||
| default | string | () |
|
|
| type | lines |
|
|
ReferenceField
Used for storing references to other Archetypes Objects.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| widget | widget | ReferenceWidget | ||
| index_method | _at_edit_accessor |
|
|
|
| type | reference |
|
|
|
| multiValued | boolean | False | Set multiValued True to allow multiple references (one-to-many), or False to allow only a single reference (one-to-one). | |
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| relationship |
|
Specifes an identifier for the type of relationships associated with the field. This should be unique within your content type, but has no larger meaning. A ReferenceField allows you to edit the set of references with a particular relationship identifier from the current content object to other objects. | 'KnowsAbout', 'Owns', 'WorksWith' | |
| allowed_types | tuple of portal types | () | Determines all the portal types that will be searched to find objects that the user can make a reference to. It also specifies the Types that should be allowed to be added directly from the reference widget. This is only activated if the addable property is set. An empty list or tuple will allow references to all portal types. | ('Document', 'File') |
| allowed_types_method | string | None | A string containing the name of a class method that will return a list of portal types to which references are allowed. | |
| vocabulary_display_path_bound | integer | 5 | Sets a limit for presentation of reference items. Up to this limit, only titles are displayed. Above the limit, the path to the referenced object is also displayed. The idea is that if there are a large number of referenced items, the user will need help to differentiate them. | |
| vocabulary_custom_label | string | None | A string containing a python expression that will be evaluated to get the displayed text for a referenced item. Your expression may use the variable "b" which will be a reference to the catalog brain returned by the reference lookup. | "b.getObject().title_or_id()" |
StringField
A field for plain-text, unformatted strings.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| default | string |
|
|
|
| type | string |
|
|
|
| widget | widget | StringWidget |
|
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| default_content_type | string MIME type | text/plain |
|
Rarely changed. |
TextField
A string field typically used for longer, multi-line strings. The string may also be transformed into alternative formats.
Standard properties| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| default | string |
|
|
|
| type | text |
|
|
|
| widget | widget | StringWidget |
|
| Name | Type | Default | Description | some possible values |
|---|---|---|---|---|
| primary | boolean | False |
Set this True to mark the field as primary for FTP or WebDAV.
|
|
| default_content_type | string MIME type | text/plain | A string designating MIME the default input type for the field. | text/plain, text/html |
| allowable_content_types | tuple of MIME-type strings | ('text/plain',) | Used in the TextArea and Rich widgets to let the user choose between different text formats in which the content is entered. | ('text/plain', 'text/html',) |
| default_output_type | string MIME type | text/plain | This is used by the accessor (get) method to and decides which MIME-Type the content should be transformed into if no special MIME-Type is demanded. | 'text/html', 'text/x-html-safe' |
3.3. Widgets Reference
Widget Attribute Topics
|
||
|---|---|---|
Common Widget Attributes
The table below describes attributes common to nearly all widgets. Illustrations and special attributes listings for each of the standard widgets follows.
| Name | Description | Possible Values |
|---|---|---|
| condition |
A string containing a TALES expression to determine whether or not a field/widget is
included on a view or edit page.
This does not distinguish between view and edit mode. |
Your TALES expression may referenc the current context as 'object' and the Plone site root as 'portal' |
| description |
Help or explanatory text for the field. Usually shown on the edit form under the label and above the input field. | |
| description_msgid | The i18n identifier for the description message. Used to translate the message. Should be unique within your product's i18n domain. | 'help_type_field' |
| label | The label that will appear in the field. | Any string, for example, Start Date for a field start_date. Also label_msgid (takes string message ids for i18n.) |
| label_msgid | The i18n identifier for the label message. Should be unique within your product's i18n domain. | 'label_type_field' |
| i18n_domain | The i18n domain specifier for your product. This should be unique for your product, and will be used to find the translation catalogs for your product. | 'productname' |
| 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 ("view", "edit"). |
| populate | If this is enabled, the view and edit fields will be populated. Usually this is 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 | Determines whether or not the field is visible view and edit mode. This is a dictionary mapping the view mode to a string describing the visibility. Choices are visible, hidden (rendered in an HTML hidden form value), invisible (not rendered at all). | For example, {'view': 'visible', 'edit': 'hidden' } means that the view will show, but the edit page will hide the value. |
Standard Widgets
BooleanWidget
Renders an HTML checkbox, from which users can choose between two values such as on/off, true/false, yes/no.
CalendarWidget
Renders a HTML input box with a helper popup box for choosing dates.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| format | string |
|
Defines the date/time format using strftime, e.g. '%d.%m.%Y', for the view.
(See the strftime section of the Python time documentation.
If this is not specified, the long form of the portal's local time format is used. |
| future_years | integer | 5 | Specifies the number of future years offered by the year drop-down portion of the date widget. Do not use both future_year and end_year. (Plone 2.5+) |
| starting_year | integer | 1999 | The first year offered by the year drop-down. (Plone 2.5+) |
| ending_year | integer | None | The final year offered by the year drop-down. Do not use both future_years and end_year. (Plone 2.5+) |
| show_hm | boolean | True | Should the widget ask for a time as well as a date? (Plone 2.5+) |
ComputedWidget
Generally used for ComputedField field type, it renders the computed value. Note that if your field has a vocabulary, and the field value is a key in that vocabulary, the widget will lookup the key in the vocabulary and show the result.
Standard Properties
| Name | Type | Default | Description |
|---|---|---|---|
| modes | tuple | ('view', 'edit') | As ComputedField is a read-only field, this property can be used to prevent the widget from appearing in edit templates, by setting it to just ('view',). |
DecimalWidget
In edit mode, renders an HTML text input box which accepts a fixed point value.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| thousands_commas | boolean | False | In view mode, formats the value to shows commas for thousands. For example, when thousands_commas is True, "7632654849635.02" is displayed as "7,632,654,849,635.02". (Note: this feature is not localized; it uses commas independent of locale. |
| whole_dollars | boolean | False | Shows whole dollars in view, leaving out the cents. Enter "1.123", and "$1" is shown. (Note: this feature is not localized; it uses the dollar sign independent of locale.) |
| maxlength | 255 | Maximum input size; sets the HTML input tag's maxlength attribute. | |
| dollars_and_cents | boolean | False | In view mode, shows dollars and cents. Enter "123.123" and "$123.12" is shown. (Note: this feature is not localized; it always uses the dollar sign, period, and two digits precision.) |
| size | 5 | Size of the input field; sets the HTML input tag's size attribute. |
FileWidget
Renders an HTML widget so a user can upload a file.
ImageWidget
Renders an HTML widget that can be used to upload, display, delete, and replace 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.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| display_threshold | integer | 102400 | Only display the image inline if img.getSize() <= display_threshold |
InAndOutWidget
In edit mode, renders a widget for moving items from one list to another. Items are removed from the source list. This can be used to choose multiple values from a list. This provides a good alternative to the MultiSelectionWidget when the vocabulary is too long for checkboxes.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| size | 6 | Size of the select widget; sets the HTML select tag's size attribute. |
| Name | Type | Default | Description |
|---|---|---|---|
| maxlength | 255 | Maximum input size; sets the HTML input tag's maxlength attribute | |
| size | 5 | Size of the input field; sets the HTML input tag's size attribute. |
KeywordWidget
This widget allows the user to select keywords or categories from a list. It is
used for the Categories field in the Categorization Schema (Plone 3+)
or the equivalent Keywords field on the Properties Tab (Plone < 3)
of a content object.
Keywords are drawn from the field vocabulary and/or the unique values for the
field in a specified catalog.
Additional keywords may be added unless the enforceVocabulary property of the
field is True.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| vocab_source | portal_catalog | Sets the catalog to search for additional vocabulary to be combined with the vocabulary defined for the field. Additional keywords from existing content are found using catalog.uniqueValuesFor(fieldName). | |
| roleBasedAdd | True | Only shows the "New keywords" input for adding keywords if the current user has one of the roles stored in the allowRolesToAddKeywords property in the site_properties property sheet in portal_properties |
LabelWidget
Used to display labels on forms -- without values or form input elements.
LinesWidget
Displays a text area so that users can enter a list of values, one per line.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| rows | integer | 5 | Rows of the lines widget; sets the HTML textarea tag's rows attribute. |
| cols | integer | 40 | Columns of the lines widget; sets the HTML textarea tag's cols attribute. |
MultiSelectionWidget
A selection widget; by default it's an HTML select widget which can be used to choose multiple values. As a checkbox users can choose one or more values from a list (useful if the list is short).
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| format | string | select | Possible values: 'select' or 'checkbox'. Uses a either a series of checkboxes or a multi-selection list. Note that checkboxes have much better usability for short vocabularies. Consider using the InAndOutWidget for longer vocabularies. |
| size | 5 | Defines the size of the multi-select list. Does not apply for checkboxes. |
PasswordWidget
Renders an HTML password input.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| maxlength | 255 | Maximum input size; sets the HTML input tag's maxlength attribute. | |
| size | 20 | Size of the input field; sets the HTML input tag's size attribute. |
Standard Properties
| Name | Type | Default |
|---|---|---|
| populate | boolean | False |
| postback | boolean | False |
| modes | ('edit',) |
PicklistWidget
Similar to the InAndOutWidget, but the values stay in the source list after selection.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| size | integer | 6 | Size of the selection box; sets the HTML select tag's size attribute. |
ReferenceWidget
Renders an HTML text input box which accepts a list of possible reference
values. Used in combination with the Reference Field.
Note: In Plone 2.5 and above, the ReferenceBrowserWidget is
a usually a better choice for a reference widget due to its ability to browse for content
referenceable objects.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| checkbox_bound | 5 | When the number of items exceeds this value, multi-selection lists are used. Otherwise, radio buttons or checkboxes are used. | |
| destination | None | May be:
|
|
| addable | False | Create createObject link for every addable type | |
| destination_types | None | Either a single type given as a string, or a list of types given as a string, defining what types we allow adding to. Only applies when addable is set on the widget. |
ReferenceBrowserWidget
A sophisticated widget for browsing, adding and deleting references.
Standard in Plone 2.5+, available for earlier versions as an add-on product.
Import from Products.ATReferenceBrowserWidget.ATReferenceBrowserWidget.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| size | integer | Size of the field if not multiValued; sets the HTML input tag's size attribute. | |
| default_search_index | string | SearchableText | when a user searches in the popup, this index is used by default |
| show_indexes | boolean | False | If True, a drop-down list is shown in the popup to select the index used for searching. If set to False, default_search_index will be used. |
| available_indexes | dict | {} |
Optional dictionary containing all the indexes that
can be used for searching along with their friendly names.
Format: {'catalogindex':'Friendly Name of Index', ... }
The friendly names are shown in the widget. Caution: If you set show_indexes True, but do not use this property to specify indexes, then all the indexes will be shown. |
| allow_search | boolean | True | If True, a search form is included in the popup. |
| allow_browse | True | Allows the user to browse content to find referenceable content. |
|
| startup_directory | string | '' | Directory shown when the popup opens. Optional. When empty, the current folder is used. See the ATReferenceBrowser readme.txt for advanced usage. |
| base_query | dict or name of method | Defines query terms that will apply to all searches, mainly useful to create specific restrictions when allow_browse=0. Can be either a dictonary with query parameters, or the name of a method or callable available in cotext that will return such a dictionary. | |
| force_close_on_insert | boolean | False | If true, closes the popup when the user choses insert. This overrides the default behavior in multiselect mode. |
| search_catalog | string | 'portal_catalog' | Specifies the catalog used for searches |
| allow_sorting | boolean | False | Allows changing the order of referenced objects (requires multiValued). |
| show_review_state | boolean | False | If True, popup will display the workflow state for objects. |
| show_path | boolean | False | If True, display the relative path (relative to the portal object) of referenced objects. |
| only_for_review_states | None | If set, content items are only referenceable if their workflow state matches one of the specified states. If None there will be no filtering by workflow state. | |
| image_portal_types | sequence | () | Use to specify a list of image portal_types. Instances of these portal types are previewed within the popup widget |
| image_method | string | None | Specifies the name of a method that is added to the image URL to preview the image in a particular resolution (e.g. 'mini' for thumbnails). |
| history_length | integer | 0 | If not zero, enables a history feature that show the paths of the last N visited folders. |
| restrict_browsing_to_startup_directory | boolean | False | If True, the user will not be able to browse above the starting directory. |
RichWidget
Allows the input of text, or upload of a file, in multiple formats that are then transformed as necessary for display. For example, allows you to type some content, choose formatting and/or upload a file. If available, the visual editor set in personal preferences is used for editing and formatting.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| rows | integer | 5 | Number of rows. (Since the visual mode of the RichWidget is controlled by JavaScript, this is not very useful.) |
| cols | integer | 40 | Number of columns. (Since the visual mode of the RichWidget is controlled by JavaScript, this is not very useful.) |
| allow_file_upload | boolean | True | If True, a file upload option is included with the field. |
SelectionWidget
Renders an HTML selection widget, which can be represented as a dropdown, or as a group of radio buttons.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| format | string | 'flex' | Possible values: 'flex', 'select', 'radio'. Uses radio buttons when set to radio, and a single-selection list when set to select. Using flex will automatically use single-selection lists for more than three settings at a time, and a single-select list for up to three settings. |
StringWidget
Renders an HTML text input box which accepts a single line of text. For simple text lines such as author.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| maxlength | integer | 255 | Maximum input length in characters; sets the HTML input tag's maxlength attribute. |
| size | 30 | Size of the input widget; sets the HTML input tag's size attribute. |
TextAreaWidget
Renders an HTML text area for typing a few lines of text. Also provides for the entry of the content in multiple formats when allowed_content_types in the enclosing TextField allows it.
Special Properties
| Name | Type | Default | Description |
|---|---|---|---|
| rows | integer | 5 | Number of rows for the edit widget; sets the HTML textarea tag's rows attribute. |
| cols | integer | 40 | Column width of the edit widget; sets the HTML textarea tag's cols attribute. |
| append_only | boolean | False | Set this attribute to True to make an append-only TextArea widget. New text gets added to the top of the existing text, dividing the new text from the existing text using the divider property. The existing text is shown below the TextArea, and is not editable. This currently works with TextArea widgets and using plain text format. |
| divider | string | ======================== | Divider text marker to use for append only text areas. Only used then the append_only property is True. |
| maxlength | integer | False | If non-zero, sets a maximum input length in characters. Since the HTML textarea tag has no maxlength property, this is enforced via a JavaScript snippet. So, it is is not applicable when JavaScript is unavailable. |
3.4. Validator Reference
Using Validators
Archetypes fields may have validators specified in the Field schema. For example, the schema for the basic page type includes the stanza:
ATDocumentSchema = ATContentTypeSchema.copy() + Schema((
TextField('text',
...
validators = ('isTidyHtmlWithCleanup',),
...
),
This specifies that the isTidyHtmlWithCleanup test will be applied to validate form input.
You may specify a sequence of validators:
validators = ('isMaxSize', 'isTidyHtmlWithCleanup',),
and the validators will tested in order.
The validators sequence may contain two kinds of entries:
- The string names of validators registered with the validation service (see Products.validation);
- Instances of classes implementing the IValidator interface (Products.validation.interfaces.IValidator.IValidator).
A validation specification using a validator class instance can look like:
validators = ( ExpressionValidator('python: int(value) == 5'), )
Registered Validators
These are validators pre-registered with the validation service. They may be specified by name.
| Name | Use | Details |
|---|---|---|
| isDecimal | Is the input a decimal number. | Allows exponent notation. |
| isInt | Is the input an integer. | |
| isPrintable | Does not contain unprintable characters | r'[a-zA-Z0-9\s]+$' |
| isSSN | Is a well-formed social-security number | Very naive: r'^\d{9}$' |
| isUSPhoneNumber | Is a valid US phone number | Looks for 10 digits, ignores spaces, parens and dashes |
| isInternationalPhoneNumber | Is a valid international phone number | Looks for any number of digits, ignores spaces, parens and dashes |
| isZipCode | Very naive: is five or nine digits | |
| isURL | Is a valid URL | Recognizes most protocols |
| isEmail | Is a valid e-mail address | A pretty good regular expression test |
| isMailTo | Is an e-mail address preceded by "mailto:" | |
| isUnixLikeName | Passes the basic test to be a Unix-style name | r"^[A-Za-z][\w\d\-\_]{0,7}$" |
| isMaxSize | Tests if an upload, file or something supporting len() is smaller than a given max size value. | Tests against a maxsize attribute on the field |
| isValidDate | Tests whether or not input value can be converted to a DateTime object. | |
| isEmpty | Input value must be empty. | |
| isEmptyNoError | Input value must be empty. | Validation will fail if input value is not empty; but no error will show. |
| isValidId | Input value is a valid identifier. | |
| isTidyHtml | Uses mx.Tidy to validate HTML input. Fails on errors and warnings. | |
| isTidyHtmlWithCleanup | Uses mx.Tidy to validate HTML input. Fails only on errors; cleans up. | |
| isNonEmptyFile | The uploaded file is not empty. | |
| isTAL | Validates as Template Attribute Language |
Useful Validation Classes
These classes are useful for creating your own validation class instances. Imports and prototypes are shown. See source for details.
ExpressionValidator
Evaluates an expression to test the input value.
from Products.validation.validators.ExpressionValidator import ExpressionValidator def ExpressionValidator(expression=None, errormsg=None)
RegexValidator
Tests value against a regular expression after removing ignorecharacters.
from Products.validation.validators.RegexValidator import RegexValidator def RegexValidator(name, regex, title=name, description='', errmsg='fails tests of %s' % name, ignore=None)
RangeValidator
Tests to see if specified minval <= input_value < maxval
from Products.validation.validators.RangeValidator import RangeValidator def RangeValidator(name, minval=0.0, maxval=0.0, title='', description='')














