Implementing the Name Chooser
So scratch the MockNameChooser code completely and let's rewrite it by basing it on the default name chooser implementation (in app.py):
from zope.app.container.contained import NameChooser
from zope.app.container.interfaces import INameChooser
class PollerNameChooser(grok.Adapter, NameChooser):
grok.context(Poller)
grok.provides(INameChooser)
def chooseName(self, name, obj):
# At first choose a name by using Zopes default NameChooser
name = super(PollerNameChooser, self).chooseName(name, obj)
# Lower case the result and replace spaces with underscores
name = name.replace(u' ', u'_').lower()
# Check the name for errors just to be careful
self.checkName(name, obj)
return name
Zope's name chooser does a couple of things for the names:
- Checks for duplicates and adds a counter if found
- Converts slashes to dashes to work with URLs
- Converts to unicode
- Strips '+' and '@' characters from the beginning, as those are special to Zope
to this behaviour, we added lower casing and space replacing to make the URLs a bit more neat. You could also register this adapter for all containers by defining the context to grok.Container class.
Now to use it in our add form, replace handle_add method with the following code:
@grok.action('Add poll')
def handle_add(self, **data):
poll = Poll()
self.applyData(poll, **data)
name = INameChooser(self.context).chooseName(poll.question, poll)
self.context[name] = poll
return self.redirect(self.url(self.context))
to adhere to the DRY pattern, we should still modify this code a bit by extracting the name chooser pattern as a method on the container, which is the first time we touch the template container. Add the following method to the Poller class:
def add_poll(self, poll):
name = INameChooser(self).chooseName(poll.question, poll)
self[name] = poll
return name
now we can use this method to add polls to this container without thinking about the naming, all that is left is to update handle_add() method to use this new method for adding the new polls to the container.

