All the default types in Plone – file, image, folder – are part of the ATContentTypes product, and are examples of archetypes. Archetypes were integrated into Plone 2.1, and allow you to create content types easily by providing a range of readymade tools so you can generate edit forms without using any HTML.
An example will perhaps best explain how Archetypes works – lets look at the familiar ‘image’ type. The edit form of an Archetype is generated using a schema, and the schema for image can be found in Products/ATContentTypes/content/image.py: here we’ve taken out some of the code to focus on the essentials:
ATImageSchema = ATContentTypeSchema.copy() + Schema(( ImageField('image', required=True, ....(lots of other stuff here, to do with image sizing and such)..... validators = (('isNonEmptyFile', V_REQUIRED), ('checkImageMaxSize', V_REQUIRED)), widget = ImageWidget( #description = "Select the image to be added by clicking the 'Browse' button.", #description_msgid = "help_image", description = "", label= "Image", label_msgid = "label_image", i18n_domain = "plone", show_content_type = False,)), ), marshall=PrimaryFieldMarshaller() )
That’s all a bit of a mouthful, so we’ll break it up and isolate the essential parts:
ATImageSchema = ATContentTypeSchema.copy() + Schema(( ImageField(
Every schema contains a collection of fields; in the edit form the short name is one field , the Title is another and so on… The reason we don’t see the title, id, or description in the above schema is they are already defined in ATContentSchema (they are common to all types); the first line of the code joins ATContentTypeSchema to the schema we are creating above.
For an image, there is only one extra field, the ImageField. Lets say we want another field to specify the camera the image was taken with; our schema will then look like:
ATImageSchema = ATContentTypeSchema.copy() + Schema(( ImageField( # all the stuff above ), StringField('camera', required=1, widget=TextAreaWidget(),), ), marshall=PrimaryFieldMarshaller() )
Archetypes provides many different kinds of field you can include – TextField, BooleanField (for yes/no values) ect. In plone.org there is a list of available Archetypes fields….
OK, lets look at the arguments of ImageField:
ImageField('image', required=True, ....(lots of other stuff here)..... validators = (('isNonEmptyFile', V_REQUIRED), ('checkImageMaxSize', V_REQUIRED)), widget = ImageWidget( # whatever goes here we'll explain # when we talk about widgets )), )
The first argument ‘image’ is the title of the field, the required=True puts the little red ‘required’ dot beside the title. Now, the next two are important:
- validators: these are classes which check that whatever we’ve entered into the field satisfies a set of conditions, and it won’t accept it if it doesn’t. For example, ImageField calls instances of two validator classes: one of them makes sure the uploaded file isn’t empty, and the other rejects the uploaded file if it is too large. There is some readymade validators at Products/validation/validators, although quite often people have the need to add extra ones of their own.
- widget: the widget is the graphical layout that the field will take; it defines how to render the field into HTML/XML. For example a StringWidget will set out a one-line box; a TextAreaWidget will set out a bigger box, like what is used for the Description. On plone.org you can see pictures of all the available Archetypes widgets ; it is very unlikely you will need to make your own. In many cases, the field type suggests what widget type to use: an ImageField will use an ImageWidget, for example.
The arguments of ImageWidget are quite straightforward:
widget = ImageWidget( #description = "Select the image to be added by clicking the 'Browse' button.", #description_msgid = "help_image", description = "", label= "Image", label_msgid = "label_image", i18n_domain = "plone", show_content_type = False,)),
The _msgid label is used by the internationalization (i18n) mechanism to generate translations in other languages.
Ok, one final thing to deal with, the marshaller, this makes Archetype fields understandable to clients such as WebDAV. As you can see above, the schema took two arguments, the field and the marshaller.
Schema ( (ImageField( all the stuff we discussed ),), marshall=PrimaryFieldMarshaller() )
PrimaryFieldMarshaller is the most common marshaller used, apparently.
Ok, so that’s the first part of my ATContentTypes exploration; the second part will deal with the question I first asked when I saw a type schema: how does all this called by a template and end up on our screens?