[BlueBream] registering utilities to dynamically populate List field/Choice vocabularies

Thierry Florac tflorac at ulthar.net
Sun Sep 5 02:56:36 EDT 2010


______________________________________________________________________
Le samedi  4 septembre,
  Jonah Crawford <jonah at tweetsprout.com> a écrit :

> I'm registering a utility which I would like to list a folder's
> contents so as to populate a drop down or multi select widget; 
> 
> problem is the utility gets called from the content type's
> interface/schema definition and there seems to be no way to pass it a
> context either for getSiteManager's lookups, or simply traversing to
> the desired folder and listing its contents. 
> 
> Naturally my example cod below doesn't work but it should shed some
> light on my (so far) unsuccessful approach..
> 
> 
> class IGroupIds(Interface):
>   """Lists a group folder's items"""
> 
>   def getGroupIds():
>       """go get'em"""
> 
> class GroupIds:
>   implements(IGroupIds)
> 
>   def getGroupIds(self, context):
>       root = getParents(context)[-2]
>       return [item for item in root['groups'].keys()]
> 
> 
> ### register it as a utility
> 
> def register_groupids_util(context, event):
>   sm = getSiteManager(context)
>   groupids = GroupIds()
>   sm.registerUtility(groupids, IGroupIds, 'groupids')
> 
> ### access it from a content type's interfaces which gets called by
> the form render
> 
> client_specified_groups = component.queryUtility(IGroupIds,
> 'groupids').getGroupIds(context)
> 
> 
> class INeedTheGroupListing(IContainer):
>   groups = List(
>                           value_type=Choice(  title= u'Client
> generated groups', values=client_specified_groups,),
>                           required=True
>                           )
______________________________________________________________________


Hi,

I think you should better use a vocabulary to define such a dynamic
list of values, as a vocabulary can be dynamic and have a context.

Something like that:

  from zope.dublincore.interfaces import IZopeDublinCore as IDC
  from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary

  class GroupsVocabulary(SimpleVocabulary):

    classProvides(IVocabularyFactory)

    def __init__(self, context):
      root = getParents(context)[-2]
      terms = [SimpleTerm(name,name,title)
               for name,title in ((zapi.getName(item),IDC(item).title)
                                  for item in root.values())]
      super(GroupsVocabulary,self).__init__(terms)

Registering is done like that in ZCML:

  <utility
    name="groupids"
    component=".GroupsVocabulary" />

or in Python code in the same way ; and the interface is modified as
follow:

  class INeedTheGroupListing(IContainer):
    groups = List(value_type=Choice(title=u'Client generated groups',
                                    vocabulary='groupids'),
                  required=True)


Hope this helps,
Thierry


More information about the bluebream mailing list