Archive | January, 2007

Archetypes and ATContentTypes, part 2: Templates and customization slots

We will now look at how these schemas are called by the edit templates, and point out slots and hooks which Archetypes have left for customization.

Let us return to our Image type: selecting this type in portal_types and looking at properties will show that atct_edit is the default editing form, as it is for all ATContent Types. There is only one line in atct_edit, calling the master macro in the base_edit template. The main function of this macro is to call other macros for different parts of the page: most of these macros are located in the edit_macros file"

  • the top slot gets filled by edit_macros/topslot
  • javascript is looked after by archetypes_custom_js/macros/javascript_head
  • css: edit_macros/css
  • header,description, body,footer all in edit_macros.

So, let’s take a closer look at some of the macros in edit_macros:

Macros in edit_macros

  • header generates document actions like print, rss ect via the document actions macro and generates a title for the edit form with the name ‘Edit (Content Type)’
  • byline generates the byline, via the document_byline macro
  • archetypes_schemata_links: not sure what this bit does yet :)
  • typedescription returns the description of the content type, which will appear at the top of the page under the title. It can be edited in portal_types without customizing, but the resulting edit will only appear in the ‘add item’ listng and not the edit form where you want it.
  • body: This is where the main action happens: for us, the interesting part of this macro is:
<metal:block define-slot="extra_top" />

        <metal:block define-slot="widgets">
          <tal:fields repeat="field fields">
            <metal:fieldMacro use-macro="python:here.widget(field.getName(), mode='edit')" />
          </tal:fields>
        </metal:block>

        <metal:block define-slot="extra_bottom" />

If we look at the above piece of code, it is essentially asking us to go through each field of the image schema and get its widget (For more on schemas and widgets, see part 1). Note the two slots ‘extra-top’ and ‘extra-bottom’ if you want to put something above or below the image widgets without changing the template.

The body macro also contains a good bit to do with sending the form, and the buttons. It contains a block defining Previous, Next (these automatically appear if there is more than one page in the edit form) Save and Cancel buttons. There is also a slot called ‘extra-buttons’ if you need to make any more buttons for your form, so you can make them in another template.

Whilst Archetypes does have a range of customization slots, one cannot make any easily reversible customizations to the schema as one might with a page template, as the files containing the schema are not stored on the zodb.

One is then left with the prospect of defining a new Archetype derived from your old one, either in a new product or as part of an existing one. Then in Extension/Install.py the portal_types tool can be manipulated to use the new type, or alternatively you can set that the old type can be just not globally allowed while the new type would be. Before you run into that course of action, there might be extra hooks for customization I havent found: for example, Villiam pointed out a post_validate hook for validators.

I am very grateful to Villiam Segeda, our resident Archetypes expert, for teaching me what little I know.

Comments { 0 }

How do they do the navigation on the plone.org site?

When you visit the plone site (http://plone.org) you see that the side navigation bar (viewable at any page besides homepage) contains only the root folders, the item and its immediate ancestors. A very nice behaviour, and one I spent a while fiddling with navigation properties trying to make happen.

But actually the solution is much simpler. Every version of Plone since 2.1 comes packaged with two identical states ‘public draft’ and ‘published’ – items in either of these two states are available to the general public. Why two identical states? Well, it does enable the user to choose which items he wants public but not available in navigation by putting the items he wants available in navigation ‘published’ and the ones he doesn’t ‘public draft’, say. Then he can go to navigation properties in preferences, check filter workflow states, and put in published into the box below.

That’s what Plone have done on their site: in addition, only the folders at site root are published, and all other content is visible, so that it will only appear in navigation if the actual page is selected.

Comments { 0 }

Hide email address from spammers

hide email

<p>Send your comments and questions Richard

<script language=javascript>

 <!--

 var contact = "Joe Blogs"

 var email = "joebloggs"

 var emailHost = "vasudevaservice.com"

 document.write("<a href=" + "mail" + "to:" + email + "@" + emailHost+ ">" + contact + "</a>" +   ".")

 //-->

</script>

</p>

NOte many plone sites have javascript automatically disenabled. to see what it looks like press more

Send your comments and questions Richard

Comments { 0 }

Archetypes and ATContentTypes, part 1: The Archetype Schema

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?

Comments { 0 }