Home What do you need? Help and documentation Plone info dynamic vocabularies, control panel configlets and plone.app.registry

Skip to content. | Skip to navigation

Elements of a web site
Beetlebrow client feedback
Testimonial

"The best and most original web design company I've come across. They understood my requirements and fulfilled them in every department."

John Davies
Managing Director
Charity Supply Company

 

More from this site »
Testimonial

Beetlebrow understood the brief perfectly and produced exactly the web site we wanted.

Since launch, they have provided great support and make changes promptly and efficiently. I'm very pleased to be working with them.

Jeremy Balcombe
Managing Director
Springdene Care Homes Group

More from this site »
Testimonial

I selected Beetlebrow to create our website from a shortlist of 10 possible providers. I was greatly impressed with the time and attention they gave to the school pre-contract, with their most senior staff attending a meeting with the school to gain a sense of its ethos and expectations for its website.

Our demands were fairly exacting and at no point did they attempt to steer us in a direct that ultimately would have made their lives simpler.

They produced a website which has received praise from the school community and many others. It has also attracted the kind of teachers we are looking for; in that respect it hit the nail on the head.

Post publication the service provided by Beetlebrow and its individual team members, with no exceptions, has been outstanding; I use that word as an educator and in its truest and most literal sense.

We continue to enjoy a client sensitive, truly professional service. I look forward to the planned refresh of our site shortly.

David Chappell
Associate Head
Holland Park School

More from this site »
Testimonial

"Well done! I would like to thank you all for making this happen. You have been a pleasure to work with and I am delighted with the end result and I am really happy that we have made the 1 September date.

Jeremy Carr-Smith
Director
Moving Office

More from this site »
Testimonial

"When I set up my business I decided to use Beetlebrow as I liked what they did and the way they did it.

"I didn't want an off-the-shelf product – I needed a custom built site that functioned in a user friendly way and created the right impression. To achieve this, more than technical expertise is required – the designers have to interpret what a "non-techie" wants and create something from scratch.

"The service I get from Beetlebrow is excellent. They are also jolly nice chaps."

Richard Max
Partner
Richard Max & Co

More from this site »
Testimonial

"Beetlebrow are a huge asset to LessBounce.

Their response time is impressive - amends are made almost instantaneously.

I don't know where we would be without them!"

Selaine Saxby
Proprietor
LessBounce.com

Testimonial

I am pleased to confirm how delighted I have been with beetlebrow services.

Their design, set up and continued maintenance has been excellent and continues to bring in a good and regular response.

Nigel Graves
Owner
Chelsea Harbour Dental Practice

More from this site »
Testimonial

"We've found Beetlebrow professional, responsive, and incredibly creative."

"When we asked them for a design, they immediately understood our brief and came back with an idea which reflected our business perfectly."

"Sales inquiries have quadrupled since the new site went up, with many new clients commenting specifically that they came to us because they were so impressed by it."

Stephen Arkell
Managing Director
Retina Productions Ltd.

 

More from this site »
Testimonial

"Beetlebrow provided us with a responsive service and a first class web site. They took care of all our requests and were helpful and knowledgeable to talk to. I'd recommend them to anyone."

Jeremy Balcombe
Managing Director
Ozone Clean Ltd

More from this site »
 

dynamic vocabularies, control panel configlets and plone.app.registry

Describes how to set up a configlet in site settings to allow managers to maintain persistent configuration data for products. Specific case deals with maintaining lists of values to provide dynamic vocabularies for selection drop-down (Choice) fields in the Member data schema.

plone.app.registry provides ui integration for plone.registry which in turn provides the local utility (per site) data store and interfaces. They are core in plone 4. NB this only appears to be true for a root zeocluster install, and not for a rootless standalone install. I don't know whether it is the root, or the zeo which is important, or both.

This documentation is based on plone.org/documentation/kb/how-to-create-a-plone-control-panel-with-plone.app.registry

However this casued a ComponentLookupError at startup when getting the registry utility similar to the one described at www.mentby.com/Group/plone-users/dynamic-vocabulary-for-userdata-field-plone-4 - the reason for this is explained better at plone.293351.n2.nabble.com/Local-utilities-ComponentLookupError-td3049621. Essentially as the registry is a local utility the python startup code to create schemas for products does not have the context of the registry as it is local to the plone site and is not available at top-level Zope. This would not be a problem if we are just accessing configuration data in standard product scripts but is an issue for start-up glue (in my case userdataschema.py). The solution is mentioned in the first link www.mentby.com/Group/plone-users/dynamic-vocabulary-for-userdata-field-plone-4 - use grok (or five.grok for Plone 4.0.5 and Zope.2.12) to provide a special interface IContextSourceBinder which is documented at plone.org/products/dexterity/documentation/manual/schema-driven-forms/customising-form-behaviour/vocabularies. This interface allows the context of the form to be passed to the registry access code which is hidden in a method at run-time. Once this was done it just worked. Other Zope-based frameworks use it to. For example in the Silva CMS documentation on Zope Schema fields http://docs.infrae.com/silva/2.3/contents/fields.html#defining-a-context-dependent-zope-vocabulary

To create the registry and control panel form:

A walk through plone.org/documentation/kb/how-to-create-a-plone-control-panel-with-plone.app.registry ignoring some bits that just weren't needed as we already had plone.app.registry and plone.registry available. But see note above about zeo/root install.

1) Define the fields that make up the control panel form by creating a zope schema interface in our products interfaces.py...

...
class IEnhancedUserDataSettings(interface.Interface):
    """ Global settings. Definition of plone.registry fields to be maintained in Control Panel.
    """
    profession_vocabulary = schema.List(title=u"Professions drop-down",
        value_type=schema.TextLine(required=True),
        required=True)

2) Set up the control panel form and the view it uses by using the same interface in controlpanel.py...

from bb.nhs.userdata.browser.interfaces import IEnhancedUserDataSettings
from plone.app.registry.browser import controlpanel
class EnhancedUserDataSettingsEditForm(controlpanel.RegistryEditForm):
    schema = IEnhancedUserDataSettings
    label = u"Enhanced User Data settings"
    description = u"Drop-down field values"
    def updateFields(self):
        super(EnhancedUserDataSettingsEditForm, self).updateFields()
    def updateWidgets(self):
        super(EnhancedUserDataSettingsEditForm, self).updateWidgets()
class EnhancedUserDataSettingsControlPanel(controlpanel.ControlPanelFormWrapper):
    form = EnhancedUserDataSettingsEditForm
	

3) Register this control panel view in the configure.zcml slug...

    <!-- Control panel -->
    <browser:page
        name="userdata-settings"
        for="Products.CMFPlone.interfaces.IPloneSiteRoot"
        class=".controlpanel.EnhancedUserDataSettingsControlPanel"
        permission="cmf.ManagePortal"
        />

4) Define a configlet to use this view in yout products control panel using generic setup - profiles/default/controlpanel.xml...

<?xml version="1.0"?>
<object
    name="portal_controlpanel"
    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
    i18n:domain="bb.nhs.userdata"
    purge="False">
    <configlet
        title="NHS Userdata"
        action_id="nhs_userdata"
        appId="bb.nhs.userdata"
        category="Products"
        condition_expr=""
        url_expr="string:${portal_url}/@@userdata-settings"
        visible="True"
        i18n:attributes="title">
            <permission>Manage portal</permission>
    </configlet>
</object>

5) Tell generic setup to use plone.app.registry in profiles/default/metadata.xml...

<?xml version="1.0"?>
<metadata>
  <version>1.0</version>
  <dependencies>
  <dependency>profile-plone.app.registry:default</dependency>
  </dependencies>
</metadata>

6) Now define the registry store itself in profiles/default/registry.xml. Again this can be fast-tracked by using the schema interface...

<?xml version="1.0"?>
<registry>
 <records interface="bb.nhs.userdata.browser.interfaces.IEnhancedUserDataSettings" />
</registry>

You should now have a working control panel configlet usable by managers.

five.grok 

More about five.grok at plone.org/products/dexterity/documentation/manual/five.grok/referencemanual-all-pages

Probably only need to do this if using registry in product start-up code to avoid the ComponentLookupError described above, though most likely it'll have other uses too.

As we wanted to access the registry to provide vocabularies at run-time for drop-downs in userdataschema.py (and avoid the ComponentLookupError) five.grok was installed using the pinned versions detailed at pypi.python.org/pypi/five.grok for five.grok 1.2.0 which is for Zope 2.12. 

1) Install five.grok

In buildout.cfg you'll need...

eggs = 
...
    five.grok==1.2.0
...
which wasn't mentioned in instructions and to be safe also added the version pinning too...
[versions]
...
# grok framework
# five.grok = 1.2.0
grokcore.annotation = 1.2
grokcore.component = 1.8
grokcore.formlib = 1.5
grokcore.security = 1.4
grokcore.site = 1.2
grokcore.view = 1.12.2
grokcore.viewlet = 1.4.1
five.localsitemanager = 2.0.3
martian = 0.11.2
...

2) Now we can make a one-off source using a grok context source binder to do its magic in userdataschema.py. Firstly by defining a method to return the vocabulary that uses the context of the form by way of this special IContextSourceBinder interface... 

...
from five import grok
from zope.component import queryUtility
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary
from plone.registry.interfaces import IRegistry
from bb.nhs.userdata.browser.interfaces import IEnhancedUserDataSettings
@grok.provider(IContextSourceBinder)
def availableProfessions(context):
    registry = queryUtility(IRegistry)
    log.info("registry: %s" % registry)
    terms = []
    
    if registry is not None:
        settings = registry.forInterface(IEnhancedUserDataSettings)
        log.info("settings: %s" % settings)
        log.info("profession_vocabulary: %s" % settings.profession_vocabulary)
        for profession in settings.profession_vocabulary:
 #           # create a term - the arguments are the value, the token, and
  #          # the title (optional)
            terms.append(SimpleVocabulary.createTerm(profession, profession.encode('utf-8'), profession))
    
    return SimpleVocabulary(terms)
...

and further on using this vocabulary in the schema...

...
   profession = schema.Choice(source=availableProfessions,
        ...
        )
...

The documentation (link below) shows the use of schema.Set() wrapping shema.Choice() but couldn't get this to work (error on writing data) and schema.Choice worked. Maybe its for the parameterised and named versions below. Not checked this out yet.

plone.org/products/dexterity/documentation/manual/schema-driven-forms/customising-form-behaviour/vocabularies describes this in more detail as well as using parameterised sources (one method for multiple vocabularies whereas the one-off source described requires a method for each vocabulary stored in the registry) and named vocabularies for using distributed components. 

Accessing the registry

In the form used to select the values from the registry we access an external method so

<select name="profession" id="select_profession">
      <option value="">
         None specified
      </option>
      <tal:block tal:repeat="profession context/getProfessions">
         <option value="None"
           tal:attributes="value profession"
           tal:content="profession">
              profession value
         </option>
      </tal:block>
</select>

 

#!/usr/bin/python
def getProfessions(self):
    from zope.component import getUtility
    from plone.registry.interfaces import IRegistry
    registry = getUtility(IRegistry)
    from bb.nhs.userdata.browser.interfaces import IEnhancedUserDataSettings
    settings = registry.forInterface(IEnhancedUserDataSettings)
#    self.plone_log('Hello from me!')
    return(settings.profession_vocabulary)

Logging for Debugging

context.plone_log may well not work for component architecture scripts so logging may need setting up...

from logging import getLogger
log = getLogger('MARKER ')
...
log.info("message: %s" % variable)
...
Search the event.log(s) for 'MARKER' and bob's...

 

Document Actions

Branding and printing for Stratford School Academy Branding and printing for Stratford School Academy

Stratford School are to become an academy, and as part of the...

Funky site for Global Art Supplies Funky site for Global Art Supplies

Global Art Supplies needed a revamped web site in keeping with their...

Chancery Bar Association chooses Beetlebrow Chancery Bar Association chooses Beetlebrow

The Chancery Bar Association needed a new web site with improved content...
Beetlebrow web design news