Personal tools
Home Webmaster Resources Zope/Plone Dynamic Vocabularies in Plone Archetypes

Dynamic Vocabularies in Plone Archetypes

There are certain instances where you will need a vocabulary to be dynamic in your Archetype instance. One example is if you want to display a list of objects contained in a Plone folder in a SelectionWidget.

The first thing to understand is that many archetype field attributes allow you to refer to a function, instead of a string.  Until now, you've probably been using vocabularies with a DisplayList that you've defined in your config.py file:


HOUR = DisplayList((
  ('1', '1'),
  ('2', '2'),
  etc....
))
StringField('hour',
                vocabulary=HOUR,
                widget=SelectionWidget(label='Hour',),
                required=1,
               ),


We could just have easily defined a function to generate the HOUR DisplayList and place it in our class definition, using the DisplayList add method to build a DisplayList on the fly.


class Event(ATContent):
    def getHours(self):
        dl = DisplayList()
        for x in range(1, 13):
          dl.add(str(x))
          dl.add(str(x))
        return dl


Now, we can call getHours from our archetypes field definition:

StringField('hour',
                vocabulary="getHours",
                widget=SelectionWidget(label='Hour',),
                required=1,
               ),


Now your thinking, there's got to be something more useful than creating a vocabulary of numbers from 1 to 12.  What if I need to show a list of sibling objects in the same Plone folder?   Let's now combine what we've just learned with Acquisition.  First include this import at the top of your script:

from Acquisition import aq_parent


Now, in the same way that we created getHours above, create a getLinks method to return all Link objects in the current folder:

def getLinks(self):
    dl = DisplayList()
    linklist = aq_parent(self).contentValues(filter={'portal_type' : 'Link'})
    for link in linklist:
        dl.add(link['id'], link['title'])
       
    return dl

Then call getLinks from the vocabulary attribute:

StringField('link',
                vocabulary="getLinks",
                widget=SelectionWidget(label='Choose an existing link',),
                required=1,
               ),

Need assistance with your project? Universal Web Services can help.
Contact us to request a quote.